本文用C#实现原型模式,也会讨论深浅拷贝,已经如何在.net中高效实现ICloneable 接口 介绍 有时候我们需要从上下文得到一个对象的拷贝,然后通过一些独立的操作来处理他。原型模式在这种情况下很适用

GoF 定义原型模式为用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype."

看一下类图

主要的参与者有 • Prototype: 抽象类或接口,定义了方法来拷贝自己 • ConcretePrototype: 克隆的具体类. • Client: 需要执行拷贝对象的软件对象 然后实现吧

使用代码

为了简化。我以一个著名的偷车游戏作为例子 我们说游戏里有一个注脚。这个主要有着一些定义游戏数据的统计量。保存游戏的时候我们就需要拷贝这个对象,然后序列化到文件中。(仅仅是举个例子,真实的游戏里很少这样做)

下面这个类抽象类就是概念中的Prototype

 

接口定义了玩家重要的信息,然后定义了一个Clone方法。然后我们定义一个具体的玩家类CJ。这样我们可以克隆当前对象,然后异步的进行序列化

这个类就是概念中的ConcretePrototype 。这里为了简化也没有其他一些方法了。

现在看看客户端软件的写法

理解深浅拷贝

上面的代码就模拟了原型模式,有一个问题就是我们使用了MemberwiseCopy 方法。而这个方法是创建浅拷贝的。如果对象里包含引用类型,引用类型的地址就会被从前者拷贝到后者。这样。两个就指向了同样的对象。

为了说明情况。我们让主角类包含更多的,叫做AdditionalDetails

 

然后抽象类将会一个AdditionalDetails 对象

 

具体类既然使用MemberwiseCopy实现拷贝

 

问题来了。两份拷贝会指向同一个AdditionalDetials 对象

画个图。看得清楚些

为了避免这种期刊。我们需要在堆上创建引用类型的拷贝,然后对应赋值

 

这样就可以了

注意。当执行深拷贝的时候,可能引用类型来包括引用类型,因此好的做法是用反射。并且递归的拷贝。直到没有引用类型,具体可参考另一文

实现ICloneable接口 ICloneable接口提供了定义拷贝方法的接口。我们可以使用ICloneable 作为概念中的Prototype,我们看一下如果实现ConcretePrototype

 

客户端代码如下

Demo下载 [downloadicon href=http://pan.baidu.com/share/link?shareid=86332&uk=1493685990]PrototypeDemo.zip[/downloadicon]

原文地址:Understanding-and-Implementing-Prototype-Pattern-i

著作权声明:本文由http://leaver.me 翻译,欢迎转载分享。请尊重作者劳动,转载时保留该声明和作者博客链接,谢谢!