`
leonardleonard
  • 浏览: 772710 次
社区版块
存档分类
最新评论

设计模式之C#实现---- ProtoType

阅读更多
作者:cuike519的专栏   http://blog.csdn.net/cuike519/

该模式的意图是:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。那么首先我们应该已经有了一个对象,同时这个对象还支持自我复制(科隆)。在FCL里面我们知道有一个接口专门用来规定这么一个契约,那就是ICloneable接口,该接口只有一个方法Clone,以下MSDN对该接口中对该接口的方法的说明:创建作为当前实例副本的新对象。Clone 既可作为深层副本实现,也可作为浅表副本实现。在深层副本中,所有的对象都是重复的;而在浅表副本中,只有顶级对象是重复的,并且顶级以下的对象包含引用。结果克隆必须与原始实例具有相同的类型或是原始实例的兼容类型。这样一来如果我们想要一个可以自我复制的对象我们可以申明一个类MyClass该类继承接口ICloneable

下面我们举一个显示生活中的例子来说明这种方法是普遍存在的的。我想我们可能都知道细胞,细胞是组成机体的最小单位(也许不是),我们知道任何(也许是部分)动物或者植物都是由一个细胞分裂的来的,所以我们可以理解细胞就是一种带有Clone方法的对象,细胞可以不断的调用该方法是我们的机体趋于完整。还可以举一个例子就是病毒,我们都经历过Sars期间,我想如果Sars没有自我复制的功能它就不可能成气候,还有一个人人都要实现的例子就是钱(我不知道是不是恰当),我们可以通过我们的努力使得1块钱变成2当然每个人的实现方法不同自然结果也就不同了(不知道是否贴切)。当然上面所据的前两个例子应该都是一种深层副本,因为他一旦被复制就是一个独立的个体,在内存中就是不同的两个地址,而潜表拷贝则不同,表面上看是两个实际上是一个对象的两个引用,也就是实际上他们存在于同一个地址,如果我们改变其中一个那么另一个也会改变。应此我们可以看出应用这种模式的关键就是如何实现Clone的方法。

       下面是PROTOTYPE的结构图(来自ROSE2003):

<!----><v:shapetype o:spt="75" coordsize="21600,21600" filled="f" stroked="f" id="_x0000_t75" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" o:connecttype="rect" gradientshapeok="t"></v:path><!----><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype>

       浅拷贝和深拷贝之间的区别:浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对象中引用型字段的值他将反映在原是对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建一个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始对象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。在FCL中的System命名空间下面有一个浅拷贝的方法叫:MemberwiseClone它是创建当前 Object 的浅表副本。在我们的例子里我想实现一个浅拷贝同时在实现一个深拷贝,这样可以加深理解。

下面是一个浅拷贝的例子:

using System;<o:p></o:p>

<o:p> </o:p>

namespace Prototype_Shallow{<o:p></o:p>

       //因为我们在FCL里面已经有这样的接口所以我们就不定义新的Prototype<o:p></o:p>

       public class ConcretePrototype1 : ICloneable{<o:p></o:p>

              private int m_ID;<o:p></o:p>

              public int ID{<o:p></o:p>

                     get{<o:p></o:p>

                            return this.m_ID;<o:p></o:p>

                     }<o:p></o:p>

              }<o:p></o:p>

              public ConcretePrototype1(int id){<o:p></o:p>

                     this.m_ID = id;<o:p></o:p>

              }<o:p></o:p>

<o:p> </o:p>

              public object Clone(){<o:p></o:p>

                     return this.MemberwiseClone();<o:p></o:p>

              }<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

       public class ConcretePrototype2 : ICloneable{<o:p></o:p>

              private int m_ID;<o:p></o:p>

              public int ID<o:p></o:p>

              {<o:p></o:p>

                     get<o:p></o:p>

                     {<o:p></o:p>

                            return this.m_ID;<o:p></o:p>

                     }<o:p></o:p>

              }<o:p></o:p>

              public ConcretePrototype2(int id){<o:p></o:p>

                     this.m_ID = id;<o:p></o:p>

              }<o:p></o:p>

              public object Clone(){<o:p></o:p>

                     return this.MemberwiseClone();<o:p></o:p>

              }<o:p></o:p>

       }<o:p></o:p>

<o:p> </o:p>

}<o:p></o:p>

我们具体的原型都继承了接口ICloneable,同时也实现了该接口里面唯一个一个方法Clone。我们可以在客户端这样创建对象ConcretePrototype1 p1 = new ConcretePrototype1(1);       ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone();首先我们创建了对象p1,接下来我们用通过p1的科隆方法得到了对象c1,这就是一种浅拷贝(因为MemberwiseClone是浅拷贝)。<o:p></o:p>

       接下来我们将要实现的是深拷贝,这个一个相对浅拷贝比较困难的工作,我们在拷贝对象的时候不但要拷贝他的数值型字段同时还要复制它的引用字段(有的时候这种工作是非常困难的也许是不可能的)。<o:p></o:p>

namespace Prototype_Deep{<o:p></o:p>

       using System.Collections;<o:p></o:p>

       public class ConcretePrototype : ICloneable<o:p></o:p>

       {<o:p></o:p>

              private int m_ID;<o:p></o:p>

              public int ID<o:p></o:p>

              {<o:p></o:p>

                     get<o:p></o:p>

                     {<o:p></o:p>

                            return this.m_ID;<o:p></o:p>

                     }<o:p></o:p>

              }<o:p></o:p>

<o:p> </o:p>

              private ArrayList m_arrayList = new ArrayList();<o:p></o:p>

<o:p> </o:p>

              public ConcretePrototype(int id)<o:p></o:p>

              {<o:p></o:p>

                     this.m_ID = id;<o:p></o:p>

                     this.m_arrayList.Add("FirstObject");<o:p></o:p>

                     this.m_arrayList.Add("SecondObject");<o:p></o:p>

                     // ...<o:p></o:p>

              }<o:p></o:p>

<o:p> </o:p>

              public object Clone()<o:p></o:p>

              {<o:p></o:p>

                     ConcretePrototype c = new ConcretePrototype(this.ID);<o:p></o:p>

                     c.m_arrayList = new ArrayList();<o:p></o:p>

                     c.m_arrayList.Add("FirstObject");<o:p></o:p>

                     c.m_arrayList.Add("SecondObject");<o:p></o:p>

                     return c;<o:p></o:p>

              }<o:p></o:p>

<o:p> </o:p>

              public ConcretePrototype DeepClone(){<o:p></o:p>

                     return (ConcretePrototype)this.Clone();<o:p></o:p>

              }<o:p></o:p>

       }<o:p></o:p>

}<o:p></o:p>

       该代码显示了如何实现深拷贝,深拷贝的原则就是对于那些引用的字段您需要newnew之前想想是不是能用前面学过的某个创建型的模式实现,这是一个好的习惯)一个出来,然后对该字段里面的对象一一拷贝,这样以来很容易出现循环拷贝,所以说深拷贝要比浅拷贝更难一些。客户端可以通过ConcretePrototype p = new ConcretePrototype(1);ConcretePrototype c = p.DeepClone();来实现克隆一个新的对象。代码如下:<o:p></o:p>

ConcretePrototype p = new ConcretePrototype(1);<o:p></o:p>

                     ConcretePrototype c = p.DeepClone();<o:p></o:p>

                     this.richTextBox1.AppendText(p.ToString()+":"+p.ID.ToString()+"\n");<o:p></o:p>

                     this.richTextBox1.AppendText(c.ToString()+":"+c.ID.ToString()+"\n");<o:p></o:p>

                     c.m_arrayList[0] = "Changed";<o:p></o:p>

                     for(int i = 0;i<=1;i++){<o:p></o:p>

                            this.richTextBox1.AppendText(c.m_arrayList[i].ToString());<o:p></o:p>

                     }<o:p></o:p>

                     this.richTextBox1.AppendText("\n");<o:p></o:p>

                     for(int i = 0;i<=1;i++){<o:p></o:p>

                            this.richTextBox1.AppendText(p.m_arrayList[i].ToString());<o:p></o:p>

                     }<o:p></o:p>

这样我们将看到结果我们在改变科隆出来的对象的时候原来的对象是不变的。前面的浅拷贝我们有做这种比较,有兴趣的读者可以试一试,在FCL中大部分的科隆都是浅拷贝,我们可以看看实现ICloneable接口的类,几乎全部都是浅拷贝。顺便说一下在工作流中关于处理(Process)对象以及其他的相关对象我们可以使用这种Clone的方法,这个您可以参看CRMWorkFlow中的类,又很多都实现了该方法。<o:p></o:p>

希望我的文章可以帮助您很好的理解设计模式中的原型,关于该模式中的详细信息您可以参看GOF的书上面说得很清楚。在这次实现中我们利用了FCL的接口,没有自己写接口但是效果是一样的。如果在文章中出现什么不对的地方忘网友指正:wu_jian830@hotmail.com谢谢您的支持,希望我们可以共同进步。<o:p></o:p>

分享到:
评论

相关推荐

    C#设计模式-吕震宇

    C#设计模式(9)-Prototype Pattern C#设计模式(8)-Builder Pattern C#设计模式(7)-Singleton Pattern C#设计模式(6)-Abstract Factory Pattern C#设计模式(5)-Factory Method Pattern C#设计模式(4)...

    C#设计模式.PDF

    C#设计模式(9)-Prototype Pattern 70 一、 原型(Prototype)模式 70 二、 Prototype模式的结构: 71 三、 程序举例: 71 四、 带Prototype Manager的原型模式 73 五、 浅拷贝与深拷贝 77 六、 Prototype模式的...

    C#设计模式大全

    C#设计模式(9)-Prototype Pattern 一、 原型(Prototype)模式 二、 Prototype模式的结构: 三、 程序举例: 四、 带Prototype Manager的原型模式 五、 浅拷贝与深拷贝 六、 Prototype模式的优点与缺点 C#...

    C#视频-面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式)

    C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式)

    C#面向对象设计模式纵横谈(视频与源码)

    C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式) C#面向对象设计模式纵横谈(7):Adapter 适配器模式(结构型模式) C#面向对象设计模式纵横谈(8):Bridge 桥接模式(结构型模式) C#面向对象设计...

    C#设计模式_设计模式_C#_

    原型模式(Prototype)结构型: 6. 适配器模式(Adapter Pattern) 7. 桥接模式(Bridge Pattern) 8. 装饰模式(Decorator Pattern) 9. 组合模式(Composite Pattern) 10. 外观模式(Facade Pattern) 11. 享元模式...

    C#设计模式(23种设计模式)

    C#设计模式(23种设计模式) 部分内容概述如下,下载可看全部哦!!! 还等什么呢?? 创建型: 1. 单件模式(Singleton Pattern) 2. 抽象工厂(Abstract Factory) 3. 建造者模式(Builder) 4. 工厂方法模式...

    设计模式面面观(10):桥接模式(Bridge Pattern)-结构型模式

    设计模式之我见(1):设计模式概述 (100%) 设计模式面面观(2):设计模式基本要素与原则 (100%) 设计模式面面观(3):单件模式(Singletion)-创建型模式 (100%) 设计模式面面观(4):工厂模式...

    原型模式(ProtoType)C#应用案例

    一个原型设计模式的应用案例,C#语言编写,有助于设计模式的理解和学以致用。

    C#面向对象设计模式纵横谈(

    6):Prototype 原型模式(创建型模式)\C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式).pdf

    C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式)

    C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式)

    C#23种设计模式_示例源代码及PDF

    多 迭代子模式 个对象聚在一起形成的总体称之为聚集, 聚集对象是能够包容一组对象的容器对象。 迭代 子 模式将迭代逻辑封装到一个独立的子对象中, 从而与聚集本身隔开。 迭代子模式简化了聚集 的界面。每一个聚集...

    C#版 24种设计模式

    适配器模式(Adapter Pattern) 提供者模式(Provider Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 原型模式(Prototype Pattern) 责任链模式(Chain of Responsibility Pattern) 中介者模式...

    设计模式代码——c#

    C#设计模式(23种设计模式) 1. 单件模式(Singleton Pattern) 2. 抽象工厂(Abstract Factory) 3. 建造者模式(Builder) 4. 工厂方法模式(Factory Method) 5. 原型模式(Prototype) 结构型: 6. 适配器...

    C#23种设计模式

    │ │ └─C#设计模式(6)——原型模式(Prototype Patt O技术博客_files │ └─PrototypePattern │ ├─bin │ │ └─Debug │ ├─obj │ │ └─Debug │ │ └─TempPE │ └─Properties ├─07.Adapter...

    C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式) (Level 300)

    C#面向对象设计模式纵横谈(6):Prototype 原型模式(创建型模式) (Level 300)

    C#面向对象设计模式纵横谈\6 Prototype原型模式创建型模式.part1.rar

    在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要资源分。敬请期待。 这是第6节:Prototype...

    C#面向对象设计模式纵横谈\6 Prototype原型模式创建型模式.part2.rar

    在这里与各位分享本人从网络上下载的C#面向对象设计模式纵横谈系列视频,共有25节,除了第一节需要各位贡献一点资源分以作为对本人上传资源的回馈,后面的其他资源均不需要资源分。敬请期待。 这是第6节:Prototype...

Global site tag (gtag.js) - Google Analytics