原型模式
模式定义
使用原型实例指定创建对象的种类,并通过拷贝这些原型对象创建新的对象。 在GOF95中原型模式被分类为创建型模式。
模式结构与说明
- Prototype:声明一个克隆自身的接口,用来约束想要克隆自己的类,让它们都要实现这里定义的克隆方法
- ConcretePrototype:实现Prototype接口的类,真正实现了对自身的克隆功能
- Client:客户端,首先获取原型实例对象,然后通过克隆原型来创建新的实例
原型模式优点:
- 向客户隐藏创建新实例的复杂性
- 在某些情况下,复制对象比创建新对象更有效
经典应用
Java的克隆机制
在Java语言中,所有类型的根类java.lang.Object支持克隆方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Object { /** * 返回当前对象的一个拷贝,拷贝的含义依赖于对象的真实类型,但是一般意味着: * x.clone() != x && x.clone().getClass() == x.getClass() && x.equals(x.clone()) * * 根据惯例,该方法返回值应当和当前对象是相互独立的,这意味着可能需要将super.clone() * 返回的对象进行一定的处理,这个修改往往意味着对可变(mutable)对象进行深拷贝,如果当前 * 类型只包含基本类型,则不需要这一处理过程 * * 当前实现实际上实现了浅拷贝行为: * 1、如果当前对象没有实现Cloneable,抛出CloneNotSupportedException * 注意所有数组类型被认为实现了Cloneable * 2、否则,创建一个新实例,并把当前对象的所有字段赋值给这个实例 * 注意任何字段本身都不会被clone() */ protected native Object clone() throws CloneNotSupportedException; } |
需要支持克隆功能的类型必须首先标记接口:
1 |
public interface Cloneable { } |
可以看到,在JDK中已经内置的原型模式的支持。
JavaScript的原型机制
JavaScript从语言层次上支持了原型模式,实际上,JavaScript的继承机制就是基于原型的继承,而不是基于类的继承。
设置一个构造函数的prototype属性为一个对象,这个对象就成为此构造函数创建出的所有对象的原型:
1 2 3 4 5 6 7 8 9 |
var protoObject = { x: 1, y: 2, z: [1, 2] }; var ConstructFunc = function(){}; var obj1 = new ConstructFunc(); console.log(obj1.z); // 从原型继承得到的属性 [1, 2] obj1.z.push(3); var obj2 = new ConstructFunc(); console.log(obj2.z); //[1, 2, 3] 原型对象的属性是浅复制的 |
模式演变
- 深克隆与浅克隆:在使用原型模式的时候,涉及到两种克隆方式。深克隆会递归的克隆所有字段;浅克隆只是拷贝复杂类型的引用地址
- 与工厂模式的比较:两者都用来创建对象实例,但是原型模式强调使用克隆的方式来创建
- 与生成器模式联用:原型模式可以用来创建某些部件
Leave a Reply