引言
在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例,如果我们用new操作符去创建这样的类实例,这可能会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配了多个一样的类实例对象,所以就引出了原型模式。原型模式可以很好的解决这个问题,因为每个类实例都是相同的,当我们需要多个相同的类实例时,没必要每次都使用new运算符去创建一个相同的类的实例对象
简介
原型模式是一种创建型设计模式,用原型实例制定创建对象的种类,并且通过复制这些原型创建新的对象
这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,就采用这种模式
原型模式的类图
原型模式的实现
在现实生活中有很多原型模式的例子,例如,细胞分裂的过程,一个细胞的有丝分裂产生两个相同的细胞;还有西游记中孙悟空变出猴子猴孙的本领和火影忍者中鸣人的隐分身术等。下面就以孙悟空为例子来演示原型模式的实现。代码如下:
using System;
///火影忍者中鸣人的影分身和孙悟空的的变都是原型模式
class Client
{
private static void Main(string[] args)
{
// 孙悟空 原型
MonkeyKingPrototype prototypeMonkeyKing = new ConcretePrototype("MonkeyKing");
// 变一个
MonkeyKingPrototype cloneMonkeyKing = prototypeMonkeyKing.Clone() as ConcretePrototype;
if (cloneMonkeyKing != null) Console.WriteLine("Cloned1:\t" + cloneMonkeyKing.Id);
// 变两个
MonkeyKingPrototype cloneMonkeyKing2 = prototypeMonkeyKing.Clone() as ConcretePrototype;
if (cloneMonkeyKing2 != null) Console.WriteLine("Cloned2:\t" + cloneMonkeyKing2.Id);
Console.ReadLine();
}
}
///
/// 孙悟空原型
///
public abstract class MonkeyKingPrototype
{
public string Id { get; set; }
protected MonkeyKingPrototype(string id)
{
this.Id = id;
}
// 克隆方法,即孙悟空说“变”
public abstract MonkeyKingPrototype Clone();
}
///
/// 创建具体原型
///
public class ConcretePrototype : MonkeyKingPrototype
{
public ConcretePrototype(string id)
: base(id)
{ }
///
/// 浅复制
///
///
public override MonkeyKingPrototype Clone()
{
// 调用MemberwiseClone方法实现的是浅复制,另外还有深复制
return (MonkeyKingPrototype)this.MemberwiseClone();
}
}
上述代码实现的是浅复制的方式,浅复制是指当前对象的字段被复制时,字段引用的对象不会被复制。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅复制,那么这两个对象将引用同一个字符串
而深复制是对对象实例中字段引用的对象也进行复制,如果一个对象有一个指定字符串的字段,并且我们对该对象进行了深复制的话,那么我们将创建一个对象和一个新的字符串,新的对象将引用新的字符串
也就是说,执行深复制创建的新对象和原来对象不会共享任何东西,改变一个对象对另外一个对象没有任何影响,而执行浅复制创建的新对象与原来对象共享成员,改变一个对象,另外一个对象的成员也会改变。
为什么要用原型模式
比如,我们有一个工具栏按钮,新建按钮,它是ToolbarButton的实例,它有长度、宽度属性等,而且属性都赋了值。现在我们要再新添加一个保存按钮,它也是ToolbarButton的实例,它也有长度、宽度属性等,不过它还没赋值,它的值和新建按钮的值一样。如果我们不用原型设计模式的话,可能重新赋一遍值。如果我们用原型设计模式的话,我们可以把新建按钮作为保存按钮的原型。那样的话就不需要再给保存按钮赋值,它的默认的长度、宽度就和新建按钮一样了。
那么,在C#中是怎样用原型的呢?
因为类的实例是引用类型,要想用原有的类中的实例的数据的话,只能用clone方法。Clone方法分为深clone和浅clone。在C#中提供了浅clone的方法,即为MemberwiseClone()
原型模式的优缺点
优点:
1、原型模式向客户端隐藏了创建新实例的复杂性
2、原型模式允许动态增加或减少产品类
3、原型模式简化了实例的创建结构,工厂方法模式需要有一个与产品类等级结构相同的等级结构,而原型模式不需要这样
4、产品类不需要事先确定产品的等级结构,因为原型模式适用于任何的等级结构
缺点:
1、每个类必须配备一个克隆方法
结语
原型模式与工厂方法模式的事项非常相似,其中原型模式中的Clone方法就类似工厂方法模式中的工厂方法,只是工厂方法模式的工厂方法是通过new运算符重新创建一个新的对象(相当于原型模式的深复制实现),而原型模式是通过调用MemberwiseClone方法来对原来对象进行复制