目录
一、模式定义
原型模式使用原型实例指定创建对象的种类,并且通过拷贝原型对象创建新的对象。实际上就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
原型模式是简单程度仅次于单例模式的简单模式,它的定义可以简单理解为对象的拷贝,通过拷贝的方式创建一个已有对象的新对象,这就是原型模式。
二、模式角色
抽象原型(Prototype)角色:规定了具体原型对象必须实现的接口(如果要提供深拷贝,则必须具有实现clone的规定)
具体原型(ConcretePrototype):从抽象原型派生而来,是客户程序使用的对象,即被复制的对象,需要实现抽象原型角色所要求的接口。
客户(Client)角色:使用原型对象的客户程序
三、模式实例
浅拷贝
public class Brand {
public void install(){
System.out.println("安装电脑品牌");
}
}
public class Computer {
private Brand brand;
public Computer(){
this.brand = new Brand();
}
@Override
protected Object clone() {
Computer clone = null;
try {
clone = (Computer)super.clone();
} catch (CloneNotSupportedException e) {
System.out.println("克隆失败...");
}
return clone;
}
public Brand getBrand(){
return this.brand;
}
public void run(){
System.out.println("小电脑能跑了");
}
}
public class Client {
public static void main(String[] args) {
Computer computer,cloneComputer;
computer = new Computer();
cloneComputer = (Computer)computer.clone();
System.out.println("computer == cloneComputer?");
System.out.println(computer == cloneComputer);
System.out.println("computer.getBrand() == cloneComputer.getBrand()?");
System.out.println(computer.getBrand() == cloneComputer.getBrand());
}
}
深拷贝
public class Brand implements Serializable {
private static final long serialVersionUID = 1L;
public void install(){
System.out.println("安装电脑品牌");
}
}
public class Computer implements Serializable {
private static final long serialVersionUID = 1L;
private Brand brand = null;
public Computer(){
this.brand = new Brand();
}
public Object deepClone() throws IOException, ClassNotFoundException{
//将对象写入流中
ByteArrayOutputStream bao=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bao);
oos.writeObject(this);
//将对象从流中取出
ByteArrayInputStream bis=new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return(ois.readObject());
}
public Brand getBrand(){
return this.brand;
}
public void run(){
System.out.println("小电脑能跑了");
}
}
public class Client {
public static void main(String[] args) {
Computer computer, cloneComputer =null;
computer = new Computer();
try {
cloneComputer = (Computer) computer.deepClone();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("computer == cloneComputer?");
System.out.println(computer == cloneComputer);
System.out.println("computer.getBrand() == cloneComputer.getBrand()?");
System.out.println(computer.getBrand() == cloneComputer.getBrand());
}
}
四、模式分析
1、优缺点
优点:可以绕过繁琐的构造函数,快速创建对象,且比直接new一个对象性能优良,因为是直接内存二进制流拷贝。原型模式非常适合于你想要向客户隐藏实例创建的创建过程的场景,提供客户创建未知类型对象的选择。
缺点:每一个类都必须配备一个克隆方法。配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类来说不是很难,而对于已经有的类不一定很容易,特别是当一个类引用不支持序列化的间接对象,或者引用含有循环结构的时候。
2、适用场景
当一个系统应该独立于它的产品创建、构成和表示时,要使用原型模式
当要实例化的类是在运行时刻指定时,如通过动态装载
为了避免创建一个与产品类层次平行的工厂类层次时
当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆原型可能比每次用合适的状态手工实例化原型类更方便一些。