保存文件路径太深-(保存文件路径太深怎么办)

常见问题 次浏览手机阅读
保存文件的路径太深 (保存文件的路径太深怎么办) 原型模式是什么?

通过复制、复制或克隆现有对象创建新对象的设计模式称为原型模式,复制对象也称为原型对象。

按照惯例,原型对象会暴露出一个 Clone 方法,给外部调用者一个从自己这里零成本克隆新对象的机会。

这里的零成本是指调用者什么都不用做,等待,原型对象在 Clone 在方法中克隆自己,给调用人,所以所有原型对象都应该按照本协议实现一个 Clone 方法。

type Prototype interface{ Clone() SpecificType}

这里我们用UML类图描述了原型模式中角色的行为及其关系

原型模式--UML类图

至于克隆原型对象,是用深拷贝还是浅拷贝?可以先理解为都是用深度复制的。完全掌握这个想法后,可以根据实际情况综合使用,比如节省空间,减少编写克隆方法的复杂性。可以先理解为都是用深度复制的。完全掌握这个想法后,可以根据实际情况综合使用,比如节省空间,减少编写克隆方法的复杂性。

原型模式更多的是解释编程模式,不限制我们如何实现。比如下面的深拷贝和浅拷贝结合使用的例子。

// 示例代码来源:https://lailin.xyz/post/prototype.htmlpackage prototypeimport ( "encoding/json" "time")// Keyword 搜索关键字type Keyword struct{ word string visit int UpdatedAt *time.Time}// Clone 这里用序列化和反序列化的方式深度复制func (k *Keyword) Clone() *Keyword{ var newKeyword Keyword b, _ := json.Marshal(k) json.Unmarshal(b, &newKeyword) return &newKeyword}// Keywords 关键字 maptype Keywords map[string]*Keyword// Clone 复制一个新的 keywords// updatedWords: 关键字列表需要更新,数组通常是从数据库中获取数据的一种方式func (words Keywords) Clone(updatedWords[]*Keyword) Keywords{ newKeywords := Keywords{}for k, v := range words{ // 这是浅拷贝,地址直接复制 newKeywords[k]= v }// 替换需要更新的字段,这里使用深拷贝 for _, word := range updatedWords{ newKeywords[word.word]= word.Clone() }return newKeywords}使用原型模式的目的

使用原型模式的主要目的是节省创建对象的时间和资源消耗,提升性能。

另一点是,例如,全球配置对象也可以作为原型对象。如果您不希望程序在运行过程中修改初始化的原型对象,导致影响其他线程执行的程序,您也可以使用原型模式快速复制原型对象,然后在运行过程中定制修改。


使用场景

当对象的创建成本相对较大,同一类别的不同对象之间没有太大差异(大多数属性值相同)时,如果对象的属性值需要复杂的计算和排序,或者需要从网络,DB等这些慢IO获取,或属性值有很深的层次,此时是原型模式发挥作用的地方。

因为对象在内存中复制自己比每次创建对象时重复上述操作要高效得多。

因为对象在内存中复制自己比每次创建对象时重复上述操作要高效得多。

再举一个例子,让我们更好地了解原型模式的优点。

利用原型模式实现文档树

下面是类似的 DOM 因为 DOM 对象的层次往往很深,所以要创建类似的DOM树木可以让我们更好地理解原型模式的优点。

这个示例代码来自:https://blog.ralch.com/articles/design-patterns/golang-prototype/package domimport ( "bytes" "fmt")// Node a document object model nodetype Node interface{ // Strings returns nodes text representation String() string // Parent returns the node parent Parent() Node // SetParent sets the node parent SetParent(node Node) // Children returns the node children nodes Children()[]Node // AddChild adds a child node AddChild(child Node) // Clone clones a node Clone() Node}// Element represents an element in document object modeltype Element struct{ text string parent Node children[]Node}// NewElement makes a new elementfunc NewElement(text string) *Element{ return &Element{ text: text, parent: nil, children: make([]Node, 0), }}// Parent returns the element parentfunc (e *Element) Parent() Node{ return e.paren // SetParent sets the element parentfunc (e *Element) SetParent(node Node){ e.parent = node}// Children returns the element children elementsfunc (e *Element) Children()[]Node{ return e.childre // AddChild adds a child elementfunc (e *Element) AddChild(child Node){ copy := child.Clone() copy.SetParent(e) e.children = append(e.children, copy)}// Clone makes a copy of particular element. Note that the element becomes a// root of new orphan treefunc (e *Element) Clone() Node{ copy := &Element{ text: e.text, parent: nil, children: make([]Node, 0), }for _, child := range e.children{ copy.AddChild(child) }return copy}// String returns string representation of elementfunc (e *Element) String() string{ buffer := bytes.NewBufferString(e.text) for _, c := range e.Children(){ text := c.String() fmt.Fprintf(buffer, "\ %s", text) }return buffer.String()}

上面的DOM对象-- Node、Element 这些都支持原型模式的要求 Clone 方法,有了这个原型克隆的能力,如果我们想创建一个好的 DOM 树上克隆了一个子分支作为一个独立的分支 DOM 树对象时,你可以像下面这样简单地执行它 Node.Clone() 复制所有节点和下面的子节点。重建树形结构比我们使用结构方法要方便得多。重建树形结构比我们使用结构方法要方便得多。

使用下面的例子DOM树结构创造了公司的等级关系,然后从任何级别克隆了一棵新树。func main(){ // 职级节点-总监 directorNode := dom.NewElement("Director of Engineering") // 职级节点-研发经理 engManagerNode := dom.NewElement("Engineering Manager") engManagerNode.AddChild(dom.NewElement("Lead Software Engineer")) // R&D经理是总监的下属 directorNode.AddChild(engManagerNode) directorNode.AddChild(engManagerNode) // 办公室经理也是总监的下属 officeManagerNode := dom.NewElement("Office Manager") directorNode.AddChild(officeManagerNode) 路由知识 fmt.Println("") fmt.Println("# Company Hierarchy") fmt.Print(directorNode) fmt.Println("") // 从R&D经理节点克隆一棵新树 fmt.Println("# Team Hiearachy") fmt.Print(engManagerNode.Clone())}

总结原型模式

总结原型模式,先说原型模式的优缺点。

原型模式的优点

克隆比有时是直接的new对象逐属性赋值的过程更加简洁高效。例如,在创建深层对象时,克隆比直接使用结构更方便。

原型模式的优点克隆比有时是直接的new对象逐属性赋值的过程更加简单高效。例如,当创建深层对象时,克隆比直接使用结构更方便。对象的状态可以通过深克隆保存,并可以帮助路由网取消操作。原型模式的缺点clone该方法位于类的内部,当对现有类进行改造时,需要修改代码,违反开关原则。当实现深克隆时,需要编写更复杂的代码,特别是当对象之间有多个嵌套时,每层对应的类别必须支持深克隆。因此,需要适当使用深克隆和浅克隆。在项目中使用原型模式时,可能需要在项目初始化时创建提供克隆能力的原型对象。在多线程环境中,当每个线程处理任务时,使用相关对象,可以复制到原型对象。然而,适合作为原型对象的数据并不多,因此原型模式在开发中的使用频率并不高。如果您有机会进行项目结构,您可以适当地考虑,并且确实需要在项目中引入这种设计模式。
喜欢 ()