定义
通过原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
结构和说明
示例代码
public class PrototypeDemo {
public static interface Prototype {
/**
* 克隆自身的方法
*
* @return 一个从自身克隆出来的对象
*/
Prototype clone();
}
public static class ConcretePrototype1 implements Prototype {
@Override
public Prototype clone() {
ConcretePrototype1 obj = new ConcretePrototype1();
// 复制属性
return obj;
}
}
public static class ConcretePrototype2 implements Prototype {
@Override
public Prototype clone() {
ConcretePrototype2 obj = new ConcretePrototype2();
// 复制属性
return obj;
}
}
public static class Client {
private Prototype prototype;
public Client(Prototype prototype) {
this.prototype = prototype;
}
public void operation() {
Prototype newPrototype = this.prototype.clone();
}
}
}
调用顺序
优缺点
优点
- 对客户端隐藏具体实现类型
原型模式的客户端只知道原型接口的类型,并不知道具体的实现类型,从而减少了客户端对这些具体实现类型的依赖。
- 在运行时动态改变具体的实现类型
原型模式可以在运行期间,由客户来注册符合原型接口的实现类型,也可以动态地改变具体的实现类型,看起来接口没有任何变化,但其实云心的已经是另外一个类实例了。因为克隆一个原型就类似于实例化一个类。
缺点
原型模式最大的缺点是在于每个子类都必须实现 clone 的操作,尤其在包含引用类型的对象时, clone 方法会比较麻烦,必要要能够递归地让所有相关对象都要正确地实现克隆。
思考
本质
克隆生成对象。
何时选用
- 如果一个系统想要独立于它想要使用的对象时,可以使用原型模式,让系统中面向接口编程,在系统需要新的对象时,可以通过克隆原型来得到。
- 如果需要实例化的类是在运行时动态指定时,可以使用原型模式,通过克隆原型来得到需要的实例。
相关模式
- 原型模式和抽象工厂模式
功能上有些相似,都是用来获取一个新的对象实例的。
不同之处在于,原型模式的着眼点是如果创建出实例对象来,最后选择的方案是克隆;而抽象工厂的着眼点则在于如何来创造产品簇,至于具体如果创建产品簇的每个对象实例,抽象工厂不是很关注。
正是因为他们的关注点不一样,所以它们也可以配合使用,比如在抽象工厂模式里面,具体创建每一种产品的时候就可以使用该产品的原型,也就是抽象工厂管产品簇,具体的每种产品怎么创建则可以选择原型模式。
- 原型模式和生成器模式
这两种模式可以配合使用。
生成器模式关注的是构建的过程,而在构建的过程中,很可能需要某个部件的实例,那么很自然地就可以应用上原型模式,通过原型模式来得到部件的实例。