一、概述
和工厂模式一样,同样对客户隐藏了对象创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过copy一个现有对象来生产新对象的。
二、原型模式
原型模式的一种形式是带原型管理器的原型模式,其类图如下:
客户(Client)角色:客户端类向原型管理器提出创建对象的请求。
抽象原型(Prototype)角色:这是一个抽象角色,通常由一个C#接口或抽象类实现。此角色给出所有的具体原型类所需的接口。在C#中,抽象原型角色通常实现了ICloneable接口。
具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。
原型管理器(Prototype Manager)角色:创建具体原型类的对象,并记录每一个被创建的对象。
三、示例(1)
我们用混合调色板管理招式来为大家演示原型模式:假定调色板的每种颜色都是有红绿蓝三种基础颜色搭配出来,使用前将各种颜色搭配出来,用户使用时只需要选定你需要的颜色名称便可得到相应的颜色。
1.首先我们需要抽象原型(Prototype)角色:ColorPrototype
abstract public class ColorPrototype { public abstract ColorPrototype clone(); }
2.然后我们添加具体原型(Concrete Prototype)角色:Color(这里我们使用浅拷贝shallow copy方式)
public class Color:ColorPrototype { private int red; private int green; private int blue; public Color(int red,int green,int blue) { this.red = red; this.green = green; this.blue = blue; } //Shallow Clone public override ColorPrototype clone() { return (ColorPrototype)this.MemberwiseClone(); } public void Display() { Console.WriteLine("RGB is:{0},{1},{2}",red,green,blue); } }
3.我们还需要原型管理器(Prototype Manager)角色:PrototypeManager
public class PrototypeManager { Hashtable colors = new Hashtable(); public ColorPrototype this[string name] { get { return (ColorPrototype)colors[name]; } set { colors.Add(name, value); } } }
4.最后我们来实现客户端代码
static void Main(string[] args) { PrototypeManager manager = new PrototypeManager(); manager["red"] = new Color(255, 0, 0); manager["green"] = new Color(0, 255, 0); manager["blue"] = new Color(0, 0, 255); manager["angry"] = new Color(255, 54, 0); manager["peace"] = new Color(128, 211, 128); manager["flame"] = new Color(211, 34, 20); string colorname = "red"; Color color = (Color)manager[colorname].clone(); color.Display(); colorname = "flame"; color = (Color)manager[colorname].clone(); color.Display(); colorname = "angry"; color = (Color)manager[colorname].clone(); color.Display(); }
四、示例(2)
在C#里面,我们可以很容易的通过Clone()方法实现原型模式。任何类,只要想支持克隆,必须实现C#中的ICloneable接口。ICloneable接口中有一Clone方法,可以在类中复写实现自定义的克隆方法。克隆的实现方法有两种:浅拷贝(shallow copy)与深拷贝(deep copy)。浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么两个对象将引用同一个字符串。而深拷贝是对对象实例中字段引用的对象也进行拷贝的一种方式,所以如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个深拷贝的话,我们将创建一个新的对象和一个新的字符串--新对象将引用新字符串。需要注意的是执行深拷贝后,原来的对象和新创建的对象不会共享任何东西;改变一个对象对另外一个对象没有任何影响。
下面让我们了解一下浅拷贝(shallow copy)与深拷贝(deep copy)的区别:
1.实现浅拷贝(shallow copy)代码:
public class ShallowCopy { public string[] ShallowObject = { "1", "2", "3" }; public Object Clone() { return this.MemberwiseClone(); } public void Display() { foreach (string i in ShallowObject) { Console.Write(i + ", "); } Console.WriteLine(); } }
2.实现深拷贝(deep copy)代码:
public class DeepCopy : ICloneable { public string[] deepObject = { "1", "2", "3" }; private DeepCopy(string[] deepObject) { this.deepObject = (string[])deepObject.Clone(); } public Object Clone() { return new DeepCopy(this.deepObject); } public void Display() { foreach (string i in deepObject) { Console.Write(i + ", "); } Console.WriteLine(); } }
3.执行结果:
9 , 2 , 3
9 , 2 , 3
9 , 2 , 3
1 , 2 , 3
五、分析Prototype模式的优缺点(摘自:http://www.cnblogs.com/zhenyulu/articles/39257.html)
Prototype模式的优点包括
1)Prototype模式允许动态增加或减少产品类。由于创建产品类实例的方法是产批类内部具有的,因此增加新产品对整个结构没有影响。
2)Prototype模式提供了简化的创建结构。工厂方法模式常常需要有一个与产品类等级结构相同的等级结构,而Prototype模式就不需要这样。
3)Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。
4)产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构。
Prototype模式的缺点:
Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,
但对已有的类进行改造时,不一定是件容易的事。