一、原型模式的定义:
所谓原型模式就是用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
为什么要用原型模式:
在应用程序中,有些对象比较复杂,其创建过程过于复杂,而且我们又需要频繁的利用该对象,如果这个时候我们按照常规思维new该对象,那么务必会带来非常多的麻烦,这个时候我们就希望可以利用一个已有的对象来不断对他进行复制就好了,这就是编程中的“克隆”。这里原型模式就可以满足我们的“克隆”,在原型模式中我们可以利用过一个原型对象来指明我们所要创建对象的类型,然后通过复制这个对象的方法来获得与该对象一模一样的对象实例。这就是原型模式的设计目的。
二、模型:
原型模式主要包含如下三个角色:
Prototype:抽象原型类。声明克隆自身的接口。
ConcretePrototype:具体原型类。实现克隆的具体操作。
Client:客户类。让一个原型克隆自身,从而获得一个新的对象。
关于克隆:
原型模式的核心就是克隆,Java中任何实现了Cloneable接口的类都可以通过调用clone()方法来复制一份自身然后传给调用者。一般而言,clone()方法满足:
(1) 对任何的对象x,都有x.clone() !=x,即克隆对象与原对象不是同一个对象。
(2) 对任何的对象x,都有x.clone().getClass()==x.getClass(),即克隆对象与原对象的类型一样。
(3) 如果对象x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
三、原型模式代码示例:
先定义一个原型抽象类,实现Cloneable接口
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/9/30 11:01
* @desc : 定义一个抽象类,实现Cloneable接口
* @version: 1.0
* </pre>
*/
public abstract class Prototype implements Cloneable {
public Prototype clone() {
Prototype prototype = null;
try {
prototype = (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return prototype;
}
abstract void show();
}
定义一个具体原型角色,继承Prototype类:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/9/30 11:06
* @desc :
* @version: 1.0
* </pre>
*/
public class ConcretePrototype extends Prototype {
private String name;
private Date time;
public ConcretePrototype() {
}
public ConcretePrototype(String name, Date time) {
this.name = name;
this.time = time;
}
@Override
void show() {
System.out.println(name + "---------" + time);
}
}
最后定义一个客户端调用:
/**
* <pre>
* @author : orange
* @e-mail : [email protected]
* @time : 2018/9/30 11:09
* @desc :
* @version: 1.0
* </pre>
*/
public class Client {
public static void main(String[] args){
Prototype con = new ConcretePrototype("cc",new Date());
Prototype prototype = con.clone();
prototype.show();
}
}
总结:
一、优点:
1、如果创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率。
2、可以使用深克隆保持对象的状态。
3、原型模式提供了简化的创建结构。
原型模式是一种类的创建模式,可以看到到目前为止的四种创建型模式,客户端(调用方)都没有直接new一个类实例出来。把new一个类实例的动作由客户端(调用方)交给别人做而不是自己做,这就是创建型模式的宗旨。使用原型模式创建对象比直接new一个对象在性能上好得多,因为Object类的clone()方法是一个native方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。使用原型模式的另一个好处是简化对象的创建,使得创建对象就像普通的复制黏贴一样简单。
二、缺点:
1、在实现深克隆的时候可能需要比较复杂的代码。
2、需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事,必须修改其源代码,违背了“开闭原则”。
三、使用场景:
1、如果创建新对象成本较大,我们可以利用已有的对象进行复制来获得。
2、如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。
3、需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。