一、原型模式介绍:

原型模式用一个原型对象来指明所要创建的对象类型,然后用复制这个原型对象的方法来创建出更多的同类型对象。

二、应用背景:

当创建一个类的实例的过程很复杂,并且我们需要创建多个这样类的实例时,如果我们用new去创建这样的类实例,会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配了多个一样的类实例对象;如果采用工厂模式来创建这样的系统的话,随着产品类的不断增加,导致子类的数量不断增多,反而增加了系统复杂程度;然而原型模式可以很好地解决这个问题,因为每个类实例都是相同的,当我们需要多个相同的类实例时,没必要每次都使用new去创建相同的类实例对象,我们只需创建一个类实例对象,如果后面需要更多这样的实例,可以通过对原来对象拷贝一份来完成创建,这样在内存中不需要创建多个相同的类实例,从而减少内存的消耗和达到类实例的复用。

二、情景例子:

生物体细胞分裂就是一个很好的原型模式例子,一个细胞有丝分裂成两个相同的细胞。

三、相关代码:

 1、创建细胞原型抽象父类:

    /// <summary>
    /// 细胞原型抽象父类
    /// </summary>
    public abstract class CellProtoType
    {
        //细胞编号
        public int id { get; set; }
        //细胞名称
        public string name { get; set; }
        public CellProtoType(int ID, string Name)
        {
            this.id = ID;
            this.name = Name;
        }

        //克隆方法,即细胞分裂
        public abstract CellProtoType Clone();
    }

2、创建具体细胞类:

    //具体原型类
    public class Cells : CellProtoType
    {
        public Cells(int ID, string Name) : base(ID, Name)
        {
        }

        /// <summary>
        /// 浅拷贝
        /// </summary>
        /// <returns></returns>
        public override CellProtoType Clone()
        {
            // 调用MemberwiseClone方法实现的是浅拷贝
            return (CellProtoType)this.MemberwiseClone();
        }
    }

3、调用

            //创建细胞原型
            CellProtoType cellprototype = new Cells(10086, "造血干细胞");
            //细胞分裂一次
            CellProtoType cell1 = cellprototype.Clone() as Cells;
            Console.WriteLine("{0}====={1}", cell1.id, cell1.name);

            //再分裂一次
            CellProtoType cell2 = cellprototype.Clone() as Cells;
            Console.WriteLine("{0}====={1}", cell1.id, cell2.name);

            Console.ReadKey();

四、拷贝形式:

可以看出上面代码实现的是浅拷贝的形式,什么是浅拷贝什么是深拷贝呢?

浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么这两个对象将引用同一个字符串。执行浅拷贝创建的新对象与原来对象共享成员,改变一个对象,另外一个对象的成员也会改变。

深拷贝是对对象实例中字段引用的对象也进行拷贝,如果一个对象有一个指向字符串的字段,并且我们对该对象进行了深拷贝的话,那么我们将创建一个新对象和一个新的字符串,新的对象将引用新的字符串。执行深拷贝创建的新对象和原来对象不会共享任何东西,改变一个对象对另外一个对象没有任何影响。

另附上利用xml序列化和反序列化深拷贝的形式:

        public T DeepCopy<T>(T obj)
        {
            object retval;
            using (MemoryStream ms = new MemoryStream())
            {
                XmlSerializer xml = new XmlSerializer(typeof(T));
                xml.Serialize(ms, obj);
                ms.Seek(0, SeekOrigin.Begin);
                retval = xml.Deserialize(ms);
                ms.Close();
            }
            return (T)retval;
        }

五、总结:

优点:

  • 原型模式向客户隐藏了创建新实例的复杂性
  • 原型模式允许动态增加或较少产品类。
  • 原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样。
  • 产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构

缺点:

  • 每个类必须配备一个克隆方法
  •  配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。