设计模式学习笔记之 Prototype
Prototype模式是用来创建一系列结构复杂的对象,这些对象经常发生变化,但是却有比较稳定的接口。Prototype模式指定创建类型的种类,通过克隆方法创建原型的新实例。
public abstract class Viewer
{
public abstract int IntToView
{
get;
set;
}
public Viewer Clone()
{
return (Viewer)this.MemberwiseClone();
}
public abstract void ViewData();
}
这里定义了一个Viewer抽象类,其中属性IntToView内容是易变的,Clone方法使用的是object. MemberwiseClone(),这是一个浅表克隆,返回值为object型,再将其类型转换为Viewer。object. MemberwiseClone()不能应用于引用类型数据,它只是将源对象的内存地址里的内容都拷贝出来,如果对象只包含值类型则没有问题,若包含引用类型,例如数组,那么新对象和源对象都会指向同一个内存地址,不符合Prototype模式的要求了。
这里我们可以应用序列化的方式来实现深拷贝,修改如下:
[Serializable]
public abstract class Viewer
{
public abstract int IntToView
{
get;
set;
}
public abstract void ViewData();
public Viewer Clone()
{
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
stream.Position = 0;
return (Viewer)formatter.Deserialize(stream);
}
} 这样就实现了深拷贝,源对象与新对象不会有任何交集了。
现在我们具体实现一个Viewer,它仍需要可序列化
[Serializable]
public class MyViewer : Viewer
{
private int intToView;
public override int IntToView
{
get
{
return intToView;
}
set
{
intToView = value;
}
}
public override void ViewData()
{
Console.WriteLine(intToView.ToString());
}
}
因为Clone方法在基类中已经写好了,在MyView中不需要修改,只需要重写虚属性和方法。
在需要创建新对象的时候:
public class MyManager
{
public void Run(Viewer viewer)
{
Viewer viewer1 = viewer.Clone();
viewer1.IntToView = 1;
Viewer viewer2 = viewer.Clone();
viewer2.IntToView = 2;
viewer1.ViewData();
viewer2.ViewData();
}
}
viewer1和viewer2都是通过对参数viewer的克隆来初始化的。如果单从效果上看的话, viewer.Clone()就好像是new了一个同传入参数viewer相同的类型,实际上是复制了viewer的所有数据成员。就这样的好处就在于它们可以被非常灵活的动态初始化,随时都可以创建和销毁。它们的类型可以随着viewer的类型改变而改变,例如Run(new MyViewer()),那么viewer1和viewer2的数据成员就是同MyViewer相同的。另外Prototype模型不需要factory类,使得模型的结构更为简化。
Clone方法是局限Prototype模式的一个问题。实现对于复杂对象的克隆是比较困难的。
另外,突然想到对于Singleton类除了声明不可继承外,还应当声明[NonSerializable]来防止被深克隆。
回到目录

浙公网安备 33010602011771号