原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。
原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。----WIKIPEDIA
首先看下面这样的一个例子,使用本人自黑一下,实现Clonable接口然后实现它的clone的方法,然后通过该方法对这个对象进行克隆。看是不是像我们期待的那样会创建出新的对象。
public class WangYang implements Cloneable{ private String name; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override protected WangYang clone() { WangYang wy = null; try { wy = (WangYang) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return wy; } @Override public String toString() { return "WangYang [name=" + name + ", address=" + address + "]"; } }
对上面的程序进行测试的测试类:
public static void main(String[] args) { WangYang wy = new WangYang(); wy.setAddress("SH"); wy.setName("wy"); WangYang wangyang = wy.clone(); System.out.println(wangyang == wy); System.out.println(wangyang); }
输出的结果为:
从这里可以看出wangyang对象和wy这个对象不是同一个对象,重新创建了新的对象。
但是稍微改一下,我有件衣服,衣服有颜色的属性,那么之前的WangYang类要增加一个属性那就是衣服的对象
private String name; private String address; private Clothes cloth;
更改完毕再次运行main测试程序,结果发现并没有对cloth进行拷贝
System.out.println(wangyang.getCloth() == wy.getCloth());
输出的结果为:true
接下来再改一下,多件衣服。
private String name; private String address; private Clothes cloth; private ArrayList<Clothes> clothesList = new ArrayList<Clothes>();
和上面的类似,在测试类中进行测试
System.out.println(wangyang == wy); System.out.println(wangyang.getClothesList() == wy.getClothesList()); System.out.println(wangyang.getCloth() == wy.getCloth()); System.out.println(wangyang);
输出的结果
看中间这两个true表示,wy对象中的cloth和clothesList没有拷贝,直接引用的原来的对象。这个地方就是浅拷贝。主要拷贝基本数据类型和String的。
那么怎么让其进行深拷贝。
对WangYang类中的clone方法进行改造,显式的去clone其内部的对象。
// 深拷贝 WangYang wy = null; try { wy = (WangYang) super.clone(); cloth = this.cloth.clone(); clothesList = (ArrayList<Clothes>) this.clothesList.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return wy;
这个地方要想让cloth对象也可以进行clone,那么需要让Clothes这个类同时实现Clonable接口实现clone方法。
此时的测试结果如何:
System.out.println(wangyang == wy); System.out.println(wangyang.getClothesList() == wy.getClothesList()); System.out.println(wangyang.getCloth() == wy.getCloth()); System.out.println(wangyang);
如图:
中间的两行全部是false了。这说明进行了深拷贝。
原型模式的优点
原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据。
注意:
1. 原型模式创建对象不会调用构造函数进行创建。直接从内存去赋值对象的数据,忽略构造函数的限制,他和之前提到的单例模式有所冲突,单例模式会将构造函数设置为私有,而原型模式却可以绕过构造函数去通过内存中的对象的数据区创建对象,所以这个地方就会有所冲突。
2. 注意深拷贝和浅拷贝。对于数组、容器对象、对象等可能需要进行深拷贝。
设计模式系列代码下载地址:设计模式系列代码下载