旧游无处不堪寻
无寻处,惟有少年心
设计模式-原型

原型模式(Prototype Pattern)是一种创建型设计模式,使你能够复制已有对象,而又无需使代码依赖它们所属的类。

解释


原型模式将克隆过程委派给被克隆的实际对象。模式为所有支持克隆的对象声明了一个通用接口,该接口让你能够克隆对象,同时又无需将代码和对象所属类耦合。通常情况下,这样的接口中仅包含一个克隆方法。

所有的类对克隆方法的实现都非常相似。该方法会创建一个当前类的对象,然后将原始对象所有的成员变量值复制到新建的类中。你甚至可以复制私有成员变量,因为绝大部分编程语言都允许对象访问其同类对象的私有成员变量。

原型模式 UML


适用场景


  1. 如果你需要复制一些对象,同时又希望代码独立于这些对象所属的具体类,可以使用原型模式
  2. 如果子类的区别仅在于其对象的初始化方式,那么你可以使用该模式来减少子类的数量

代码示例


using System;
namespace PrototypePatternDemo
{
public class Person
{
public int Age;
public DateTime BirthDate;
public string Name;
public IdInfo IdInfo;

public Person ShallowCopy()
{
return (Person) this.MemberwiseClone();
}

public Person DeepCopy()
{
Person clone = (Person) this.MemberwiseClone();
clone.IdInfo = new IdInfo(IdInfo.IdNumber);
clone.Name = String.Copy(Name);
return clone;
}
}

public class IdInfo
{
public int IdNumber;

public IdInfo(int idNumber)
{
this.IdNumber = idNumber;
}
}

class Program
{
static void Main(string[] args)
{
Person p1 = new Person();
p1.Age = 42;
p1.BirthDate = Convert.ToDateTime("1977-01-01");
p1.Name = "Jack Daniels";
p1.IdInfo = new IdInfo(666);

Person p2 = p1.ShallowCopy();
Person p3 = p1.DeepCopy();

Console.WriteLine("Original values of p1, p2, p3:");
Console.WriteLine(" p1 instance values: ");
DisplayValues(p1);
Console.WriteLine(" p2 instance values:");
DisplayValues(p2);
Console.WriteLine(" p3 instance values:");
DisplayValues(p3);

p1.Age = 32;
p1.BirthDate = Convert.ToDateTime("1900-01-01");
p1.Name = "Frank";
p1.IdInfo.IdNumber = 7878;
Console.WriteLine("\nValues of p1, p2 and p3 after changes to p1:");
Console.WriteLine(" p1 instance values: ");
DisplayValues(p1);
Console.WriteLine(" p2 instance values (reference values have changed):");
DisplayValues(p2);
Console.WriteLine(" p3 instance values (everything was kept the same):");
DisplayValues(p3);
// output

// Original values of p1, p2, p3:
// p1 instance values:
// Name: Jack Daniels, Age: 42, BirthDate: 01/01/77
// ID#: 666
// p2 instance values:
// Name: Jack Daniels, Age: 42, BirthDate: 01/01/77
// ID#: 666
// p3 instance values:
// Name: Jack Daniels, Age: 42, BirthDate: 01/01/77
// ID#: 666

// Values of p1, p2 and p3 after changes to p1:
// p1 instance values:
// Name: Frank, Age: 32, BirthDate: 01/01/00
// ID#: 7878
// p2 instance values (reference values have changed):
// Name: Jack Daniels, Age: 42, BirthDate: 01/01/77
// ID#: 7878
// p3 instance values (everything was kept the same):
// Name: Jack Daniels, Age: 42, BirthDate: 01/01/77
// ID#: 666
}

public static void DisplayValues(Person p)
{
Console.WriteLine(" Name: {0:s}, Age: {1:d}, BirthDate: {2:MM/dd/yy}",
p.Name, p.Age, p.BirthDate);
Console.WriteLine(" ID#: {0:d}", p.IdInfo.IdNumber);
}
}
}