重温设计模式 --- 原型模式

引言

原型模式是一种创建型设计模式,它允许我们创建一个对象的副本,而不需要显式地使用构造函数来创建一个新的对象。这种模式通常用于创建那些具有复杂创建过程或需要大量资源的对象。

在原型模式中,我们首先定义一个原型接口,该接口包含一个克隆方法。然后我们创建一个原型对象,该对象实现了原型接口并提供了自己的克隆方法。最后,我们可以使用原型对象的克隆方法来创建新的对象,而无需重新实例化原型对象。

IClone接口

需要定义一个IClone接口。这个类中应该包含一个 Clone 方法,用于克隆自身。

public interface IClone<T> where T : class
{
    public T Clone();
}

原型类

定义一个具体原型类,它实现IClone接口,并实现了Clone方法

public class ConcretePrototype : IClone<ConcretePrototype>
{
    private string _name;

    public ConcretePrototype(string name)
    {
        _name = name;
    }

    public ConcretePrototype Clone()
    {
        return (ConcretePrototype)this.MemberwiseClone();
    }

    public void SetName(string name)
    {
        _name = name;
    }

    public void PrintName()
    {
        Console.WriteLine($"Name: {_name}");
    }
}

在具体原型类中,我们实现了 Clone 方法,并使用了 MemberwiseClone 方法来复制对象。此外,我们还添加了一个 SetName 方法和一个 PrintName 方法,用于演示对象的复制和修改。

:::tip{title="提示"}

  1. 使用 Clone 方法来复制对象。需要注意的是,在复制对象时,我们需要使用 MemberwiseClone 方法或其他深拷贝方法来复制对象本身,而不是复制它的引用。此外,如果需要复制对象的引用类型成员,我们需要在具体原型类中对它们进行深拷贝
  2. 原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。
  3. 执行Clone方法复制对象时,不执行其构造函数
    :::

接下来,我们可以使用具体原型类来创建新的对象。具体地说,我们可以先创建一个原型对象,然后调用它的 Clone 方法来复制它,并修改复制出的对象的状态。

ConcretePrototype prototype = new ConcretePrototype("prototype");

ConcretePrototype clone = (ConcretePrototype)prototype.Clone();

prototype.PrintName(); // Name: prototype

clone.PrintName(); // Name: prototype

clone.SetName("clone");

prototype.PrintName(); // Name: prototype

clone.PrintName(); // Name: clone

在这段代码中,我们首先创建了一个名为 prototype 的具体原型对象,并输出它的名字。然后,我们调用了 prototypeClone 方法来复制它,并将结果保存在名为 clone 的变量中。接着,我们修改了 clone 的名字为 "clone",并分别输出 prototypeclone 的名字,以证明它们是不同的对象。

总结

原型模式适用于以下情况:

  • 当需要创建的对象的类型由程序在运行时确定时,原型模式比工厂模式更加灵活。
  • 当需要创建的对象的创建过程较为复杂,或者需要初始化较长时间时,原型模式可以避免重复创建对象的开销。
  • 当需要创建的对象与其它对象具有相似的属性和方法时,原型模式可以避免重复编写相同的代码。