设计模式之【原型模式(prototype)】

在软件开发中,有时候可能会需要创建一些特别复杂的对象,如果系统中已经存在同样类型的对象,并且不同的属性个数相差不大的话,用Prototype模式可能是一个理想的选择。

定义 :用原型实例指定创建物件的种类,并且通过拷贝这些原型创建新的物件。

Prototype 模式允许一个物件再创建另外一个可定制的物件,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型物件传给那个要发动创建的物件,这个要发动创建的物件通过请求原型物件拷贝它们自己来实施创建。
方法很简单,只要调用对象的clone方法返回一个新的对象就可以了。但是为什么没有其他新的方法来实现这个模式呢?因为Java中的Object提供了clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单.

在这个clone方法中,我们只要调用Object的克隆方法返回一个对象,就可以以最简单的方式实现Prototype模式。

在其他编程语言中,就需要创建一个当前类的新的对象,然后把当前对象本身的各属性的值复制一份给新创建的对象,并且返回新对象即可。


从上图中的main函数的调用过程来看,也可以很清晰地看出Prototype模式和其他创建型模式的不同:Prototype模式创建对象不是通过new一个类,而是通过一个现有的对象实例来的。

什么时候应该使用prototype模式呢?
1.当你要创建的对象与现有运行时对象相似度很大时
2.为了避免创建类的工厂类导致层次复杂度增加时
3.当类的实例只有不多的几种状态时(此时需要引进原型管理器)

Prototype模式常用在一些对象管理器中。这些对象管理器本身一般为单例模式,主要负责对象的创建和返回。由于返回的对象的类型基本上是一致的,而且返回的对象的各项属性大多保持一致,只有极少数属性才需要修改,所以用Prototype无疑是极好的选择。

需要注意的是:浅拷贝和深拷贝的区别。

简单的讲,浅拷贝就是只对当前对象的直属属性进行复制,如果其属性是基本类型的话,就复制原对象的值;如果其属性是其他对象的话,就复制对象的地址。而深拷贝则是麻烦的多,如果其属性是对象的话,就需要创建一个新的子属性的对象,并且对这个对象的各项属性进行复制,如果子属性还有子属性的话,则需要递归的进行复制操作。

一切就看需求,如果那些属性的值不会被变更的话,那么只需要实现浅拷贝即可;否则,深拷贝就是必须的。


import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
class Temp implements java.io.Serializable{
private final static long serialVersionUID =-1342345235354L;
}
public class Prototype implements Cloneable,Serializable{
private String str;
private Temp temp;
//clone
@Override
public Object clone() throws CloneNotSupportedException{
return (Prototype)super.clone();
}
//deep clone
public Object deepClone() throws IOException, ClassNotFoundException{
ByteArrayOutputStream bo= new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bo);
oos.writeObject(this);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bi);
return ois.readObject();
}
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public Temp getTemp() {
return temp;
}
public void setTemp(Temp temp) {
this.temp = temp;
}
}

public class TestPrototype {

/**
* @param args
* @throws CloneNotSupportedException
* @throws ClassNotFoundException
* @throws IOException
*/
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Prototype pt = new Prototype();
Temp temp = new Temp();
pt.setTemp(temp);
pt.setStr("Hello world");
System.out.println("clone++++++++++++++++++++++++++++++++");
Prototype _pt = (Prototype) pt.clone();
System.out.println("pt.Str:"+pt.getStr());
System.out.println("_pt.str:"+_pt.getStr());
System.out.println("++++++++++++++++++++++++++++++++++++++");

System.out.println("改变pt的属性值,然后再比较:");
pt.setStr("你好!");
System.out.println("pt.Str:"+pt.getStr());
System.out.println("_pt.str:"+_pt.getStr());
System.out.println("比较pt和_pt中temp的值:");
System.out.println("pt.getTemp:"+pt.getTemp());
System.out.println("_pt.getTemp:"+_pt.getTemp());
System.out.println("++++++++++++++++++++++++++++++++++++++++");

System.out.println("采用deepClone:");
Prototype dp = new Prototype();
dp.setTemp(temp);
Prototype _dp = (Prototype)dp.deepClone();
System.out.println("比较Temp的值");
System.out.println("dp.getTemp:"+dp.getTemp());
System.out.println("_dp.getTemp():"+_dp.getTemp());
}

}

运行结果:
clone++++++++++++++++++++++++++++++++
pt.Str:Hello world
_pt.str:Hello world
++++++++++++++++++++++++++++++++++++++
改变pt的属性值,然后再比较:
pt.Str:你好!
_pt.str:Hello world
比较pt和_pt中temp的值:
pt.getTemp:prototype.Temp@de6ced
_pt.getTemp:prototype.Temp@de6ced
++++++++++++++++++++++++++++++++++++++++
采用deepClone:
比较Temp的值
dp.getTemp:prototype.Temp@de6ced
_dp.getTemp():prototype.Temp@1270b73
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值