大话设计模式之原型模式
来源:互联网 发布:达内 测计网络营 编辑:程序博客网 时间:2024/05/17 04:02
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象
原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节,基本代码如下:
//原型类abstractclass Prototype{ private string id; public Prototype(string id) { this.id = id; } public string Id() { get{ retrun id; } } //抽象类关键就是有这样一个Clone方法 public abstract Prototype Clone(); }; //具体原型类classConcretPrototype1 :Prototype{ public ConcretPrototype1(string id) :base(id) { } public override Prototype Clone() { //https://msdn.microsoft.com/zh-cn/library/system.object.memberwiseclone.aspx //MemberwiseClone方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。 //如果字段是值类型的,则对该字段执行逐位复制。 如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。 return (Prototype)this.MemberwiseClone(); } }; //客户端代码voidmain(){ ConcretPrototype1 p1 = new ConcretPrototype1("I"); ConcretPrototype1 c1 = (ConcretPrototype1)p1.Clone(); //克隆类 ConcretPrototype1 的对象p1就能得到新的实例c1}
其实,原型抽象类Prototype是用不着的。
因为,克隆实在是太常用了,.Net提供了ICloneable接口,其中唯一的方法就是Clone(), 这样只要实现这个接口就可以完成原型模式了
下面给出一个实例:
原题是需要给出几份相同的简历,但是我觉得有些牵强,于是就把题目改为生成几额类似的矩形,可以有细节上的差异。(虽然我把原题的代码结构图贴上来了)
classRectangle :ICloneable{ private int length; private int width; private string color; private string birthtime; private string author; public Rectangle(string author) { this.author = author; } //detail infomation public void SetTangleInfo(int length, intwidth, string color) { this.length = length; this.width = width; this.color = color; } //set create time public void SetTime(string birthtime) { this.birthtime = birthtime; } //show public void Display() { Console.WriteLine("{0}{1} {2}", length, width, color); Console.WriteLine("CreateTime : {0}, Author : {1} ", birthtime, author); } public Object Clone { return (Object)this.MemberwiseClone(); }}; //客户端voidmain(){ Rectangle a = new Rectangle("Ben"); a.SetTangleInfo(10,20,"red"); a.SetTime("201504091049"); //只需要调用Clone方法就可以实现新矩形的生成,并且可以修改新矩形的细节 Rectangle b = (Rectangle)a.Clone(); b.SetTime("201504091050"); Rectangle c = (Rectangle)a.Clone(); c.SetTangleInfo(20,10,"blue"); a.Display(); b.Display(); c.Display();}
这样一来,如果每个细节都一样,那么我们的代码可以显得十分清爽。
性能也得到了提高,比如看对象a的初始化,假设是复杂的项目,如果每个对象都这样,那么就太低效了。
一般在初始化信息不发生变化的情况下,克隆是最好的办法。这既隐藏了对象创建的细节,又对性能是大大的提高。
相当于是不用重新初始化对象,而是动态的获得对象运行时的状态。
但是,我们也发现,我们使用的MemberwiseClone() 函数,根据描述是浅拷贝,这里再把那段话拿过来看看:
【https://msdn.microsoft.com/zh-cn/library/system.object.memberwiseclone.aspx
MemberwiseClone方法创建一个浅表副本,方法是创建一个新对象,然后将当前对象的非静态字段复制到该新对象。
如果字段是值类型的,则对该字段执行逐位复制。 如果字段是引用类型,则复制引用但不复制引用的对象;因此,原始对象及其复本引用同一对象。】
当前矩形类中的数据都是值类型(int,string),所以没有什么问题,但是如果类中有对象引用,那么引用的对象数据是不会被克隆过来的。
接下来我们修改一下矩形类,让其中的时间类型不再是string类型而是一个类。那么在使用的时候就需要注意了。
下面就给出实现了深克隆的代码: (关于仅仅使用浅克隆的结果想必很容易想到,所以就不贴上来了)
不过这里我依旧把简历的类结构图贴上来:
classBirthTime :ICloneable{ private int year; public int Year { get{ return year; } set{ year = value; } } private int month; public int Month { get{ return month; } set{ month = value; } } private int day; public int Day { get{ return day; } set{ day = value; } } public Object Clone() //时间类实现Clone方法 { return (Object)this.MemberwiseClone(); }}; classRectangle :ICloneable{ private int length; private int width; private string color; private BirthTime bt; private string author; public Rectangle(string author) { this.author = author; bt = new BirthTime(); } public Rectangle(BirthTime bt) { //这个构造函数是为了将来深克隆用的 this.bt = (BirthTime)bt.Clone(); //这里我们虽然是浅克隆,但是我们这里也只需要浅克隆就行了,因为该类里全是值类型而没有引用的 } //detail infomation public void SetTangleInfo(int length, intwidth, string color) { this.length = length; this.width = width; this.color = color; } //set create time public void SetTime(int year, int month,int day) { bt.Year = year; bt.Month = month; bt.Day = day; } //show public void Display() { Console.WriteLine("{0}{1} {2}", length, width, color); Console.WriteLine("CreateTime : {0} {1} {2}, Author : {3} ", bt.Year, bt.Month, bt.Day, author); } public Object Clone() { Rectangle obj = new Rectangle(this.bt); //这里就用到了之前准备好的构造函数,能这么用也依赖于BirthTime类中没有引用且实现的浅克隆(如果BirthTime中有引用,那么就需要一层一层的浅克隆来实现接下来一层的深克隆了) obj.length = this.length; obj.width = this.width; obj.color = this.color; obj.author = this.author; return obj; //最终返回一个深复制的矩形对象 }}; //客户端voidmain(){ Rectangle a = new Rectangle("Ben"); a.SetTangleInfo(10, 20, "red"); a.SetTime(2015,4,9); //只需要调用Clone方法就可以实现新矩形的生成,并且可以修改新矩形的细节 Rectangle b = (Rectangle)a.Clone(); b.SetTime(2015,4,10); Rectangle c = (Rectangle)a.Clone(); c.SetTangleInfo(20, 10, "blue"); a.Display(); b.Display(); c.Display();}
这样,我们的输出结果就不再像浅克隆一样,a和b的时间类指向同一个时间对象,导致输出相同的时间了。
- 大话设计之原型模式
- 大话设计模式之原型模式
- 大话设计模式之原型模式
- 大话设计模式之原型模式
- 大话设计模式之原型模式
- java设计模式大话之原型模式
- 大话设计模式读后感之原型模式
- 大话设计模式之原型模式
- 大话设计模式读书笔记之原型模式
- 《大话设计模式》之原型模式
- 大话设计模式--原型模式
- 大话设计模式-原型模式
- 大话设计模式-原型模式
- 大话设计模式-原型模式
- 大话设计模式----原型模式
- 大话设计模式之原型模式中的复制
- <六>读<<大话设计模式>>之原型模式
- 《大话设计模式》java实现之原型模式
- 【LeetCode】125.Valid Palindrome
- Redis-Sentinel
- Java中Runnable和Thread的区别
- 双系统win7下u盘安装ubuntu12.04
- linux下创建svn版本库
- 大话设计模式之原型模式
- web开发问题汇总
- JZ2440如何烧写裸板程序,在 Linux 下使用 dnw 和 u-boot 烧写系统 和 用Tftp 下载
- 关于iOS中动态获取获得字体的行数的更新
- Navicat for MySQL远程访问服务器MySQL数据库
- iOS开发实用技巧—打包app发给测试人员测试
- eclipse 常用快捷键 - 源码阅读超好用
- MySQL存储引擎总结
- IOS笔记之,post一个Json到服务器