Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5016757
  • 博文数量: 891
  • 博客积分: 17977
  • 博客等级: 上将
  • 技术积分: 8636
  • 用 户 组: 普通用户
  • 注册时间: 2005-08-26 09:59
个人简介

一个好老好老的老程序员了。

文章分类

全部博文(891)

文章存档

2020年(8)

2019年(40)

2018年(88)

2017年(130)

2015年(5)

2014年(12)

2013年(41)

2012年(36)

2011年(272)

2010年(1)

2009年(53)

2008年(65)

2007年(47)

2006年(81)

2005年(12)

分类: C#/.net

2020-05-01 22:17:50

所谓原型模式,就是创建一个类的基本原型,然后通过克隆这个基本原型来创建新的对象,通常克隆的效率要远远高于通过构造来创建新对象。因为克隆对象的时候不需要了解创建对象时的细节。

原型模型的结构和实现简介

面向对象语言C#提供了Clone方法(ICloneable接口),所以要想一个类的实例能被Clone,这个类需要实现ICloneable接口。

1.原型模型的结构

原型模式包含以下主要角色。
  1. 接口原型类:规定了具体原型对象必须实现的接口ICloneable
  2. 具体原型类:实现接口原型类的 clone() 方法,它是可被复制的对象。
  3. 访问类:使用具体原型类中的 clone() 方法来复制新的对象。
基结构如下图所示:

2.原型模式的实现

原型模式的克隆分为浅克隆和深克隆。C#中只要实现了ICloneable接口的类的对象都可以进行Clone操作,这里的克隆一般是浅克隆。
比如下面的代码。

点击(此处)折叠或打开

  1. public class PrototypeObject : ICloneable
  2.     {
  3.         #region ICloneable 成员

  4.         public object Clone()
  5.         {
  6.             Console.WriteLine("我是克隆函数输出。");
  7.             return MemberwiseClone();
  8.         }

  9.         public PrototypeObject()
  10.         {
  11.             Console.WriteLine("我是构造函数输出。");
  12.         }
  13.         #endregion
  14.     }
调用主函数:

点击(此处)折叠或打开

  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             PrototypeObject p = new PrototypeObject();
  6.             PrototypeObject p1 = p.Clone() as PrototypeObject;
  7.             Console.Read();
  8.         }
  9.     }
这里实现的是浅克隆。
关于深克隆的实现,我们实现第二版代码。
我们在上一版代码的基础上,增加一个SubPrototypeObject类,并做为PrototypeObject的一个属性存存在。然后对克隆前后的SubPrototypeObject进行判断。增加的代码如下(标记为Region Ver1)。
增加一个SubPrototypeObject

点击(此处)折叠或打开

  1. public class SubPrototypeObject
  2.     {
  3.         public SubPrototypeObject()
  4.         {
  5.             Console.WriteLine("我是子类的构造函数输出。");
  6.         }
  7.     }
原来的PrototypeObject变化如下(见Ver1的Region)
点击(此处)折叠或打开
  1. public class PrototypeObject : ICloneable
  2.     {
  3.         #region ICloneable 成员

  4.         public object Clone()
  5.         {
  6.             Console.WriteLine("我是克隆函数输出。");
  7.             return MemberwiseClone();
  8.         }

  9.         public PrototypeObject()
  10.         {
  11.             Console.WriteLine("我是构造函数输出。");
  12.             #region Ver1
  13.             SubObject = new SubPrototypeObject();
  14.             #endregion
  15.         }

  16.         #region Ver1
  17.         public SubPrototypeObject SubObject { get; set; }
  18.         #endregion
  19.         #endregion
  20.     }
同时调用类发生如下变化:

点击(此处)折叠或打开

  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             PrototypeObject p = new PrototypeObject();
  6.             PrototypeObject p1 = p.Clone() as PrototypeObject;
  7.             #region Ver1
  8.             Console.WriteLine("p.SubObject == p1.SubObject is {0}",p.SubObject == p1.SubObject);
  9.             #endregion
  10.             Console.Read();
  11.         }
  12.     }
输出如下:

从结果不难看出,克隆对象的子对象和原对象的子对象是同一个对象。
我们想实现深克隆,即让原对象的子对象和克隆对象的子对外象不一样。需要实现第二版代码。如下:
深克隆对象类:
点击(此处)折叠或打开
  1. public class SubPrototypeObject
  2.     {
  3.         #region Ver2
  4.         public object Clone()
  5.         {
  6.             Console.WriteLine("我是子类的克隆函数输出。");
  7.             return this.MemberwiseClone();
  8.         }
  9.         #endregion
  10.         public SubPrototypeObject()
  11.         {
  12.             Console.WriteLine("我是子类的构造函数输出。");
  13.         }
  14.     }
克隆对象类
点击(此处)折叠或打开
  1. public class PrototypeObject : ICloneable
  2.     {
  3.         #region ICloneable 成员

  4.         public object Clone()
  5.         {
  6.             Console.WriteLine("我是克隆函数输出。");
  7.             #region Ver2
  8.             PrototypeObject cloneObj = MemberwiseClone() as PrototypeObject;
  9.             cloneObj.SubObject = this.SubObject.Clone() as SubPrototypeObject;
  10.             return cloneObj;
  11.             #endregion
  12.         }

  13.         public PrototypeObject()
  14.         {
  15.             Console.WriteLine("我是构造函数输出。");
  16.             #region Ver1
  17.             SubObject = new SubPrototypeObject();
  18.             #endregion
  19.         }

  20.         #region Ver1
  21.         public SubPrototypeObject SubObject { get; set; }
  22.         #endregion
  23.         #endregion
  24.     }
见Region Ver2代码。运行结果如下:

能看出构造对象的子对象和克隆对象的子对象已经不是同一个对象了。
此处我们需要注意的是,SubPrototypeObject没有实现ICloneable接口,只是添加了一个Clone方法,照样实现Clone目标,但这不符合C#的规范,在我们判断一个对象是否可Clone的时候一般是判断是否实现了ICloneable接口。所以建议还是按照标准来,将此类实现ICloneable接口。此处小变更不再贴代码,大家直接看附件的工程吧。
源码和类图见附件压缩包。
Prototype.zip
阅读(71) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~