设计模式(0)简单工厂模式html
设计模式(2)工厂方法模式(Factory Method)github
设计模式(3)抽象工厂模式(Abstract Factory)设计模式
源码地址spa
原型模式是一种经常使用的建立型模式,原型模式的通常定义为用原型实例指定建立对象的种类,并经过拷贝这些原型建立新的对象设计
原型模式要求对象必须具备一个能够“克隆”自身的方法,这样就能够经过这个克隆自身的方法建立一个新的同一类型的实例。咱们一般将这个克隆自身的方法定义在抽象的接口上,直接经过接口调用其内部包含的克隆方法,建立一个具体的对象。这样就能够实现经过原型模式建立具体对象,无需关注这个对象自己的类型,也不用关心其内部的具体实现,而无须再去经过new去建立具体的类型的实例。code
原型模式的结构图以下htm
Prototype:声明一个克隆自身的接口,用来约束想要克隆自身的类,全部想要实现克隆自身这一功能的类须要继承此接口,而且实现该接口里定义的克隆自身的方法对象
ConcretePrototype:实现了Prototype接口的具体实现类,这些类中负责Clone这一方法的具体实现
Client:客户端,经过原型实例克隆自身的Clone方法建立新的对象实例
在war3中,有一个道具叫作“幻象权杖”其做用是使用后能制造目标单位的一个幻象。咱们不考究幻象的其余具体细节,从外形上是与本体彻底一摸同样的。
咱们先建立一个英雄的接口
/// <summary> /// 英雄接口定义 /// </summary> public interface IHero { /// <summary> /// 身体特征 /// </summary> string Body { get; set; } /// <summary> /// 武器 /// </summary> string Weapon { get; set; } /// <summary> /// 坐骑 /// </summary> string Mount { get; set; } }
DH类具体实现
/// <summary> /// 恶魔猎手 /// </summary> public class DH : IHero { /// <summary> /// 身体特征 /// </summary> public string Body { get { return "黑夜给了我黑色眼睛,我却用它去寻找光明。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "艾辛诺斯双刃。"; } set { } } /// <summary> /// 坐骑 /// </summary> public string Mount { get { return "我有这双脚有这双腿。"; } set { } } }
POM类具体实现
/// <summary> /// 月亮女祭司 /// </summary> public class POM : IHero { /// <summary> /// 身体特征 /// </summary> public string Body { get { return "夜幕只为朱颜改,群星陨落无穷。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "索利达尔·群星之怒。"; } set { } } /// <summary> /// 坐骑 /// </summary> public string Mount { get { return "艾斯卡达尔。"; } set { } } }
幻象权杖类实现
/// <summary> /// 幻象权杖 /// </summary> public class WandOfIllusion { public static IHero Use(IHero hero) { IHero result = null; if (hero is DH) { result = new DH(); } else if (hero is POM) { result = new POM(); } return result; } }
客户端使用
class Program { static void Main(string[] args) { DH dh = new DH(); var dh1 = WandOfIllusion.Use(dh); // 对dh使用幻象权杖 Console.ReadLine(); } }
这样能够实现英雄使用幻象权杖复制自身这一基本需求,可是明显存在一下问题
一、经过幻象权杖复制英雄对象自己 这一通用的功能代码中,不该该强依赖具体的英雄类,应该是与具体的实现无关的。
二、难以扩展,要实现其余英雄使用幻象权杖这一操做,就必须修改幻象权杖类,里面须要增长更多的类型判断。并且咱们这里只作了简要的对象建立处理,而实际中各个对象的建立过程是千差万别的,这样咱们的幻象权杖类就会变得愈来愈难以维护。
基于问题的出现以及上述对原型模式的介绍,咱们可使用原型模式解决这一问题。
0、英雄接口增长Clone方法
按照原型模式的要求,咱们须要在英雄接口中增长一个Clone方法,全部英雄的具体实现类实现此方法,完成复制英雄的具体细节。
/// <summary> /// 英雄接口定义 /// </summary> public interface IHero { /// <summary> /// 身体特征 /// </summary> string Body { get; set; } /// <summary> /// 武器 /// </summary> string Weapon { get; set; } /// <summary> /// 坐骑 /// </summary> string Mount { get; set; } /// <summary> /// Clone自己接口定义 /// </summary> /// <returns></returns> IHero Clone(); }
一、具体英雄实现类实现Clone方法
/// <summary> /// 恶魔猎手 /// </summary> public class DH : IHero { /// <summary> /// 身体特征 /// </summary> public string Body { get { return "黑夜给了我黑色眼睛,我却用它去寻找光明。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "艾辛诺斯双刃。"; } set { } } /// <summary> /// 坐骑 /// </summary> public string Mount { get { return "我有这双脚有这双腿。"; } set { } } /// <summary> /// Clone /// </summary> /// <returns></returns> public IHero Clone() { IHero hero = new DH(); //TODO:进行其余Clone相关操做 return hero; } }
/// <summary> /// 月亮女祭司 /// </summary> public class POM : IHero { /// <summary> /// 身体特征 /// </summary> public string Body { get { return "夜幕只为朱颜改,群星陨落无穷。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "索利达尔·群星之怒。"; } set { } } /// <summary> /// 坐骑 /// </summary> public string Mount { get { return "艾斯卡达尔。"; } set { } } /// <summary> /// Clone /// </summary> /// <returns></returns> public IHero Clone() { IHero hero = new POM(); //TODO:进行其余Clone相关操做 return hero; } }
二、修改幻象权杖类
/// <summary> /// 幻象权杖 /// </summary> public class WandOfIllusion { public static IHero Use(IHero hero) { IHero result = null; //if (hero is DH) //{ // result = new DH(); //} //else if (hero is POM) //{ // result = new POM(); //} result = hero.Clone(); return result; } }
至此咱们的幻象权杖通用类,已经与具体的英雄实现类无关了。
三、浅克隆和深克隆
浅克隆:只克隆值类型的属性数据
深克隆:除了要复制浅克隆须要复制的值类型属性数据外,也要复制引用类型的属性数据。
优势
对客户端调用隐藏具体实现类细节,减小外部调用对具体实现类的依赖
缺点
每一个实现类都必须实现Clone方法,尤为在包含引用类型的深克隆时,须要逐级让全部的引用类型实现Clone