C#设计模式系列:原型模式(Prototype)
1、原型模式简介
1.1>、定义
原型模式(Prototype)用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
1.2>、使用频率
中
1.3>、原型模式应用
首先从实际生活来了解原型模式的由来,假设你有一份非常好的讲义,你的朋友也想要一份,那么怎么办?重新手抄一份?显然不是,当然是用复印机复印一份来得方便、直接,并且准确性也高,这种用原型来复制而不是重新创建的思维方式就是原型模式的核心思想。
Prototype Pattern也是一种创建型模式,它关注的是大量相同或相似对象的创建问题。应用原型模式就是建立一个原型,然后通过对原型来进行复制的方法,来产生一个和原型相同或相似的新对象,或者说用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
2、原型模式结构
2.1>、结构图
2.2>、参与者
原型模式参与者:
◊ Prototype:原型类,声明一个Clone自身的接口;
◊ ConcretePrototype:具体原型类,实现一个Clone自身的操作。
在原型模式中,Prototype通常提供一个包含Clone方法的接口,具体的原型ConcretePrototype使用Clone方法完成对象的创建。
3、原型模式结构实现
Prototype.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.PrototypePattern.Structural { /// <summary> /// The 'Prototype' abstract class /// </summary> public abstract class Prototype { private string _id; /// <summary> /// Constructor /// </summary> public Prototype(string id) { this._id = id; } /// <summary> /// Gets id /// </summary> public string Id { get { return _id; } } public abstract Prototype Clone(); } }
ConcretePrototype1.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.PrototypePattern.Structural { public class ConcretePrototype1 : Prototype { /// <summary> /// Constructor /// </summary> public ConcretePrototype1(string id) : base(id) { } /// <summary> /// Returns a shallow copy /// </summary> /// <returns></returns> public override Prototype Clone() { return (Prototype)this.MemberwiseClone(); } } }
ConcretePrototype2.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.PrototypePattern.Structural { public class ConcretePrototype2 : Prototype { /// <summary> /// Constructor /// </summary> public ConcretePrototype2(string id) : base(id) { } /// <summary> /// Returns a shallow copy /// </summary> /// <returns></returns> public override Prototype Clone() { return (Prototype)this.MemberwiseClone(); } } }
Client.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.PrototypePattern.Structural; namespace DesignPatterns.PrototypePattern { class Client { static void Main(string[] args) { // Create two instances and clone each ConcretePrototype1 p1 = new ConcretePrototype1("I"); ConcretePrototype1 c1 = (ConcretePrototype1)p1.Clone(); Console.WriteLine("Cloned: {0}", c1.Id); ConcretePrototype2 p2 = new ConcretePrototype2("II"); ConcretePrototype2 c2 = (ConcretePrototype2)p2.Clone(); Console.WriteLine("Cloned: {0}", c2.Id); } } }
运行输出:
Cloned: I
Cloned: II
请按任意键继续. . .
4、原型模式实践应用
ColorPrototype.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.PrototypePattern.Practical { /// <summary> /// The 'Prototype' abstract class /// </summary> public abstract class ColorPrototype { public abstract ColorPrototype Clone(); } }
Color.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.PrototypePattern.Practical { /// <summary> /// The 'ConcretePrototype' class /// </summary> public class Color : ColorPrototype { private int _red; private int _green; private int _blue; /// <summary> /// Constructor /// </summary> public Color(int red, int green, int blue) { this._red = red; this._green = green; this._blue = blue; } /// <summary> /// Create a shallow copy /// </summary> public override ColorPrototype Clone() { Console.WriteLine("Cloning color RGB: {0,3},{1,3},{2,3}", _red, _green, _blue); return this.MemberwiseClone() as ColorPrototype; } } }
ColorManager.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace DesignPatterns.PrototypePattern.Practical { /// <summary> /// Prototype manager /// </summary> public class ColorManager { private Dictionary<string, ColorPrototype> _colors = new Dictionary<string, ColorPrototype>(); /// <summary> /// Indexer /// </summary> public ColorPrototype this[string key] { get { return _colors[key]; } set { _colors.Add(key, value); } } } }
Client.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using DesignPatterns.PrototypePattern.Practical; namespace DesignPatterns.PrototypePattern { class Client { static void Main(string[] args) { ColorManager colormanager = new ColorManager(); // Initialize with standard colors colormanager["red"] = new Color(255, 0, 0); colormanager["green"] = new Color(0, 255, 0); colormanager["blue"] = new Color(0, 0, 255); // User adds personalized colors colormanager["angry"] = new Color(255, 54, 0); colormanager["peace"] = new Color(128, 211, 128); colormanager["flame"] = new Color(211, 34, 20); // User clones selected colors Color color1 = colormanager["red"].Clone() as Color; Color color2 = colormanager["peace"].Clone() as Color; Color color3 = colormanager["flame"].Clone() as Color; } } }
运行输出:
Cloning color RGB: 255, 0, 0 Cloning color RGB: 128,211,128 Cloning color RGB: 211, 34, 20 请按任意键继续. . .
5、原型模式应用分析
原型模式可以适用于以下情形:
◊ 当一个系统应该独立于它的产品创建、构成和表示时;
◊ 当要实例化的类是在运行时刻指定时,例如通过动态装载来创建一个类;
◊ 为了避免创建一个与产品类层次平行的工厂类层次时;
◊ 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并Clone它们可能比每次用合适的状态手工实例化该类更方便一些。
原型模式具有以下特点:
◊ 对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目;
◊ 允许客户只通过注册原型实例就可以将一个具体产品类并入到系统中,客户可以在运行时刻建立和删除原型;
◊ 减少了子类的构造。原型模式是Clone一个原型而不是请求工厂方法创建一个,所以它不需要一个与具体产品类平行的Creator类层次;
◊ 原型模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响旧系统;
◊ 产品类不需要非得有任何事先确定的等级结构,因为原型模式适用于任何的等级结构;
◊ 原型模式的最重要缺点就是每一个类必须配备一个Clone方法,而且这个Clone方法需要对类的功能进行通盘考虑。这对全新的类来说不是很难,但对已有的类进行改造时,不一定是容易的事。