原型模式是一种创建型设计模式,它的模式动机是:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式适用于:
1.当一个系统应该独立于它的产品创建,构成和表示时;
2.当要实例化的类是在运行时刻指定时,例如,通过动态装载;
3.为了避免创建一个与产品类层次平行的工厂类层次时;
4.当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
原型模式组成:(1)原型抽象类;(2)具体对象类;
举个例子,现在游戏中要生成许多一样或者相似的哥布林,一个个new出对象十分消耗资源,我们可以使用原型模式的浅拷贝拷贝原有的对象,首先创建原型抽象类,使用抽象类或者接口均可(个人觉得接口合适一点,毕竟其中的克隆是一种行为,不过抽象类亦可):
然后便可创建具体对象哥布林类:
哥布林类中有克隆方法和其他属性,当用户想要克隆哥布林时,首先需创建一个哥布林对象,然后直接调用该对象的Clone()方法即可,不需new出新的对象。
这里要注意使用object.MemberWiseClone()获取一个对象的实例属于浅拷贝,对实例的简单类型属性进行全值拷贝(包含string类型),对复杂类型属性只拷贝了引用。对于克隆哥布林的名字这样的简单类型进行更改时,原型哥布林名字不会改变,但若是对克隆哥布林的复杂类型如defence进行修改,那么原型哥布林的defence也会发生变化,因为克隆时复制的是引用。
原型模式的优点是隐藏了创建实例的繁琐过程,只需通过Clone方法就可以获取实例对象,在性能上比直接 new 一个对象更加优良。
原型模式的缺点是需要添加一个Clone方法,使用MemberwishClone方法来获取实例的浅拷贝副本时要注意复杂类型。
另外,实现深拷贝常用的有两种方法:①将原始实例序列化,然后反序列化赋值给副本对象;②浅拷贝+递归的方式,类似于遍历文件夹,对所有的复杂属性、复杂属性内部的复杂属性都进行浅拷贝。