1.原型模式的介绍
原型模式是一个创建型的模式,该模式应该有一个样板实例,用户从这个样板对象中复制出一个内部属性
一致的对象,这个过程俗称克隆,被复制的实例就是所称的原型,原型可定制。原型模式多用于创建复杂
的或者构造耗时的实例,因为这种情况下,复制一个已经存在的实例可使程序运行更高效。
2.定义
用原型实例指定创建对象的种类,并通过复制这些原型创建新的对象。
3.使用场景:
1>.类的初始化需要消耗非常多的资源,这个资源包括数据,硬件资源等。原型复制可以避免这些消耗。
2>.通过new产生一个对象需要非常繁琐的数据准备或访问权限,这时可以使用原型复制。
3>.一个对象需要提供给其它对象访问,而且各个调用者可能都需要修改其值时,可以考虑用原型模式复
制多个对象供调用者使用,即保护性拷贝。
注意:通过实现Cloneable接口的原型模式在调用clone函数构造实例时并不一定比通过new操作速度快,
只有当通过new构造对象较为耗时或者说成本较高时,通过clone方法才能够获得效率上的提升。因此,
在使用Cloneable时需要考虑构建对象的成本以及做一些效率上的测试。当然原型模式也不一定非要实现
Cloneable接口,也有其它的实现方式。
4.总结
原型模式本质上就是对象拷贝,与C++中拷贝构造函数有些类似,它们之间容易出现的问题也都是深拷贝
,浅拷贝。使用原型模式可以解决构建复杂对象的资源消耗问题,能够在某些场景下提升创建对象的效率
。还有一个重要的用途就是保护性拷贝,也就是某个对象对外可能是只读的,为了防止外部对这个只读对
象修改,通常可以通过返回一个对象拷贝的形式实现只读的限制。
优点:原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体
内产生大量的对象时,原型模式可以更好地体现其优点。
缺点:即是优点也是缺点,直接在内存中拷贝,构造函数是不会执行的,在实际开发当中应该注意这个潜
在的问题。优点就是减少了约束,缺点也是减少了约束。
5.简单实例
public class WrodDocument implements Cloneable {
private String mText;
private ArrayList<String> mImages = new ArrayList<>();
public WrodDocument() {
System.out.println("------------------WordDocument构造函数----------------");
}
@Override
protected WrodDocument clone() {
try {
WrodDocument doc = null;
doc = (WrodDocument) super.clone();
doc.mText = this.mText;
doc.mImages = (ArrayList<String>) this.mImages.clone();
return doc;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public String getmText() {
return mText;
}
public void setmText(String mText) {
this.mText = mText;
}
public ArrayList<String> getmImages() {
return mImages;
}
public void addImages(String img) {
this.mImages.add(img);
}
public void showDocument(){
System.out.println("---------------Word Content Start---------------");
System.out.println("Text:"+mText);
System.out.println("Images List:");
for (String imgName:mImages){
System.out.println("image name:"+imgName);
}
System.out.println("---------------Word Content End------------------");
}
}
public class Client {
public static void main(String[] args) {
WrodDocument originDoc=new WrodDocument();
originDoc.setmText("这是一篇文档");
originDoc.addImages("图片1");
originDoc.addImages("图片2");
originDoc.addImages("图片3");
originDoc.showDocument();
WrodDocument doc2=originDoc.clone();
doc2.showDocument();
doc2.setmText("这是修改过的Doc2文本");
originDoc.setmText("测试修改");
originDoc.addImages("测试");
doc2.showDocument();
originDoc.showDocument();
}
}