1.定义
用原型实例创建指定对象的种类,并通过复制这些原型创建新对象。
2.使用场景
a.类初始化需要消耗非常多的资源,包括数据资源、硬件资源,通过原型复制,避免这种资源消耗。
b.通过new产生一个对象需要非常繁琐的数据准备或访问权限。
c.一个对象需要提供给其他对象访问,而且各个调用者都需要修改其值时,可以考虑复制多个对象供调用者使用,实现保护性拷贝。
3.简单实现
通过实现Cloneable接口和覆写clone方法实现原型模式
//文档对象 实现Cloneable接口 public class WordDoc implements Cloneable{ private String txt; private String mImages ; public WordDoc(){ System.out.print("WordDoc构造函数"); } public String getTxt() { return txt; } public void setTxt(String txt) { this.txt = txt; } public String getmImages() { return mImages; } public void setmImages(String mImages) { this.mImages = mImages; } public String showDoc() { return " Word txt:" + txt +" , imgs: " + mImages +" "; } //覆写clone方法 @Override protected WordDoc clone() { try { WordDoc doc = (WordDoc) super.clone(); doc.txt = this.txt; doc.mImages = this.mImages; return doc; }catch (Exception e){ e.printStackTrace(); } return null; } }
public static void main(String[] args){ //创建一个原始文档 WordDoc wordDoc = new WordDoc(); wordDoc.setTxt("原始文档"); wordDoc.setmImages("原始图片"); System.out.print("\n" + wordDoc.showDoc()); //以原始文档为原型 拷贝副本 WordDoc doc1 = wordDoc.clone(); System.out.print("\n"+ doc1.showDoc()); //修改副本 doc1.setTxt("doc1 修改"); doc1.setmImages("doc1 修改图片"); System.out.print("\n" + doc1.showDoc()); //查看原始文档 System.out.print("\n" + wordDoc.showDoc()); }
输出:
注意clone方法并不是Cloneable接口中的,而是Object中的方法,Cloneable也是一个接口标识,它表明这个类的对象是可拷贝的,如果没有实现Cloneable接口却调用了clone()会抛出异常。
还用通过clone拷贝的对象并不会执行构造函数!如在构造函数中需要有特殊的初始化操作类型,在使用Cloneable实现拷贝的时候需要注意构造函数不会执行。
还需要注意深拷贝浅拷贝问题,即在拷贝对象的时候,对引用型的字段也要采用拷贝的形式。
4.小结
原型模式本质上是对象的拷贝,可以解决对构建复杂对象资源消耗问题,还有一个重要用途就是保护性拷贝,如果这个对象是只读对象,可以通过返回一个对象的拷贝的形式。
优点:
原型模式是内存中二进制流的拷贝,要比直接new对象性能好很多
缺点:
开发过程中要主要构造函数不会执行的问题