设计模式之C#实现(四)---- ProtoType

原创 2003年09月20日 00:57:00

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

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

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

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

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

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

using System;

 

namespace Prototype_Shallow{

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

       public class ConcretePrototype1 : ICloneable{

              private int m_ID;

              public int ID{

                     get{

                            return this.m_ID;

                     }

              }

              public ConcretePrototype1(int id){

                     this.m_ID = id;

              }

 

              public object Clone(){

                     return this.MemberwiseClone();

              }

       }

 

       public class ConcretePrototype2 : ICloneable{

              private int m_ID;

              public int ID

              {

                     get

                     {

                            return this.m_ID;

                     }

              }

              public ConcretePrototype2(int id){

                     this.m_ID = id;

              }

              public object Clone(){

                     return this.MemberwiseClone();

              }

       }

 

}

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

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

namespace Prototype_Deep{

       using System.Collections;

       public class ConcretePrototype : ICloneable

       {

              private int m_ID;

              public int ID

              {

                     get

                     {

                            return this.m_ID;

                     }

              }

 

              private ArrayList m_arrayList = new ArrayList();

 

              public ConcretePrototype(int id)

              {

                     this.m_ID = id;

                     this.m_arrayList.Add("FirstObject");

                     this.m_arrayList.Add("SecondObject");

                     // ...

              }

 

              public object Clone()

              {

                     ConcretePrototype c = new ConcretePrototype(this.ID);

                     c.m_arrayList = new ArrayList();

                     c.m_arrayList.Add("FirstObject");

                     c.m_arrayList.Add("SecondObject");

                     return c;

              }

 

              public ConcretePrototype DeepClone(){

                     return (ConcretePrototype)this.Clone();

              }

       }

}

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

ConcretePrototype p = new ConcretePrototype(1);

                     ConcretePrototype c = p.DeepClone();

                     this.richTextBox1.AppendText(p.ToString()+":"+p.ID.ToString()+"/n");

                     this.richTextBox1.AppendText(c.ToString()+":"+c.ID.ToString()+"/n");

                     c.m_arrayList[0] = "Changed";

                     for(int i = 0;i<=1;i++){

                            this.richTextBox1.AppendText(c.m_arrayList[i].ToString());

                     }

                     this.richTextBox1.AppendText("/n");

                     for(int i = 0;i<=1;i++){

                            this.richTextBox1.AppendText(p.m_arrayList[i].ToString());

                     }

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

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

我所理解的设计模式(C++实现)——原型模式(Prototype Pattern)

解决的问题: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。这个其实和C++的拷贝构造函数的作用是一致的,实际上就是动态抽取当前对象运行时的状态。 类图结构:      ...
  • LCL_data
  • LCL_data
  • 2013年04月06日 16:01
  • 9201

浅谈Java设计模式(五)原型模式(Prototype)

前言: 原型模式虽然是创建型的模式,但是与工程模式没有关系,从名字即可看出,该模式的思想就是将一个对象作为原型,对其进行复制、克隆,产生一个和原对象类似的新对象。本小结会通过对象的复制,进行讲解。在...
  • caihongdao123
  • caihongdao123
  • 2016年07月08日 16:41
  • 7660

设计模式之Prototype(c++)

Prototype模型: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象----克隆(clone)对象。...
  • richerg85
  • richerg85
  • 2013年12月04日 22:03
  • 1753

无废话C#设计模式之五:Prototype

无废话C#设计模式之五:Prototype 意图        用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 场景        游戏场景中的有很多相似的敌人,它们的技能都一样,但...
  • rise51
  • rise51
  • 2011年01月18日 11:08
  • 209

常见设计模式的解析和实现(C++)之四-Prototype模式

作用: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 UML结构图: 抽象基类: 1)Prototype:虚拟基类,所有原型的基类,提供Clone接口函数 接...
  • muweiyou
  • muweiyou
  • 2012年05月19日 10:26
  • 440

设计模式的解析和实现(C++)之四-Prototype模式

作用:     用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。     UML结构图:     抽象基类:     1)Prototype:虚拟基类,所有原型的基...
  • AngryXXQ
  • AngryXXQ
  • 2012年11月12日 12:51
  • 295

C# 设计模式之原型模式(Prototype)

class WorkExperience:ICloneable { private string workDate; public string WorkDat...
  • riyao1990
  • riyao1990
  • 2013年12月06日 13:31
  • 192

C#设计模式之原型模式(Prototype Pattern)

一、引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为...
  • MR_yuan24
  • MR_yuan24
  • 2014年10月18日 21:28
  • 543

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

  • 2008年09月13日 15:53
  • 8.26MB
  • 下载

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

  • 2009年12月20日 12:51
  • 10.36MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式之C#实现(四)---- ProtoType
举报原因:
原因补充:

(最多只允许输入30个字)