本篇内容介绍了“prototype模式实现时要考虑什么问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
实现
因为在像C++这样的静态语言中,类不是对象,并且运行时刻只能得到很少或者得不到任何类型信息,所以Prototype特别有用。而在Smalltalk或Objective C这样的语言中Prototype就不是那么重要了,因为这些语言提供了一个等价于原型的东西(即类对象)来创建每个类的实例。Prototype模式在像Self [US87]这样基于原型的语言中是固有的,所有对象的创建都是通过克隆一个原型实现的。
简单说就是在C++中没有提供原型机制,所以需要自己构建原型模式;反之,对于语言中已经提供等价机制的时候,直接使用就好。
当实现原型时,要考虑下面一些问题:
1 ) 使用一个原型管理器
当一个系统中原型数目不固定时(也就是说,它们可以动态创建和销毁),要保持一个可用原型的注册表。客户不会自己来管理原型,但会在注册表中存储和检索原型。客户在克隆一个原型前会向注册表请求该原型。我们称这个注册表为原型管理器(prototype manager)。
对于原型可以动态创建的情况,需要有个地方存放它们以备需要时使用。这个管理机制就是原型管理器。它至少对外提供两个功能,登录和检索。一个是输入原型,一个是输出原型。注意这里的客户指的是用原型的模块而不是软件的使用者。
原型管理器是一个关联存储器( associative store),它返回一个与给定关键字相匹配的原型。它有一些操作可以用来通过关键字注册原型和解除注册。客户可以在运行时更改甚或浏览这个注册表。这使得客户无需编写代码就可以扩展并得到系统清单。
关联指的是关键字和原型之间的关系。原型的登录和检索都需要这种关系。通常情况下,还需要浏览已经登录的原型的机制,这样客户即使完全不知道这些原型是怎么来的也可以方便地使用它们了。
2 ) 实现克隆操作
Prototype模式最困难的部分在于正确实现Clone操作。当对象结构包含循环引用时,这尤为棘手。
例如C++中,A,B两个对象循环引用的情况,由于这是A,B两个对象都至少出现两次,在进行Clone操作时需要用某种方式(硬编码或者某种识别机制)来决定哪个是实体,哪个是引用。
大多数语言都对克隆对象提供了一些支持。例如,Smalltalk提供了一个copy的实现,它被所有Object的子类所继承。C++提供了一个拷贝构造器。但这些设施并不能解决“浅拷贝和深拷贝”问题[GR83]。也就是说,克隆一个对象是依次克隆它的实例变量呢,或者还是由克隆对象和原对象共享这些变量?
考虑C++中克隆操作的情况,假设某个类有一个指针类型的数据成员指向另外一个对象,克隆处理如何知道这个对象是类组成的一部分(需要克隆)还是某个共通对象的参照(不需要克隆)呢?
浅拷贝简单并且通常也足够了,它是Smalltalk所缺省提供的。C++中的缺省拷贝构造器实现按成员拷贝,这意味着在拷贝的和原来的对象之间是共享指针的。但克隆一个结构复杂的原型通常需要深拷贝,因为复制对象和原对象必须相互独立。因此你必须保证克隆对象的构件也是对原型的构件的克隆。克隆迫使你决定如果所有东西都被共享了该怎么办。
就像实例化类得到的对象,克隆得到的对象也会被独立使用。所以必须使用深拷贝而不是浅拷贝。在进行Clone处理时,还必须考虑在所有对象都是共享的情况下该怎么做(这句可能不准确,但实在没有更好的说法了)。
如果系统中的对象提供了Save和Load操作,那么你只需通过保存对象和立刻载入对象,就可以为Clone操作提供一个缺省实现。 Save操作将该对象保存在内存缓冲区中,而Load则通过从该缓冲区中重构这个对象来创建一个复本。
这种方式省去了直接硬编码克隆的麻烦。但是需要另外的空间来保存数据。很多时候会使用语言库中提供的系列化功能。
3) 初始化克隆对象
当一些客户对克隆对象已经相当满意时,另一些客户将会希望使用他们所选择的一些值来初始化该对象的一些或是所有的内部状态。一般来说不可能在Clone操作中传递这些值,因为这些值的数目由于原型的类的不同而会有所不同。一些原型可能需要多个初始化参数,另一些可能什么也不要。在Clone操作中
传递参数会破坏克隆接口的统一性。
一般来讲都会希望对克隆得到的对象进行一定程度的修改。但是因为这种修改会随着类的不同,应用场景的不同而有所变化,所以不大可能通过Clone处理的参数来消化。通常的做法是得到对象以后进行修改。
可能会这样,原型的类已经为(重)设定一些关键的状态值定义好了操作。如果这样的话,客户在克隆后马上就可以使用这些操作。否则,你就可能不得不引入一个Initialize操作(参见代码示例一节),该操作使用初始化参数并据此设定克隆对象的内部状态。注意深拷贝Clone操作——一些复制在你重新初始化它们之前可能必须要被删除掉(删除可以显式地做也可以在I n i t i a l i z e内部做)。
在修改克隆得到对象的时候,如果已经存在修改状态(或属性)的操作,直接使用就好;如果没有就需要引入一个initialize操作(而不是增加设定操作)。克隆操作是深拷贝的时候需要注意,有些成员在初始化之前需要先删除通过克隆得到的内容。这个删除可以是显式的,也可以在Initialize内部进行。
“prototype模式实现时要考虑什么问题”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。