一、介绍及定义
①介绍:原型模式是一种创建型的模式。原型两个字表明了该模式应该有一个样板实例,用户从这个样板实例中复制出
一个内部属性一致的对象,这个过程通俗的讲就是“克隆”。这个被复制的实例就称为“原型”。
②定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
③场景:用于创建复杂的和耗时的实例
注:通过实现Cloneable接口的原型模式在调用clone函数构造实例时并不一定比new构建速度快,只有通过new对象成本较高或者耗时时,才会使用clone构建对象。
二、UML类图
三、案例
创建
public class WordDocument implements Cloneable{
private String name;
private ArrayList<String> mlist=new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<String> getMlist() {
return mlist;
}
public void addString(String text) {
this.mlist.add(text);
}
@Override
protected WordDocument clone() {
try {
WordDocument wordDocument= (WordDocument) super.clone();
wordDocument.name = this.name;
wordDocument.mlist=this.mlist;
return wordDocument;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void showDocument(){
Log.e("TAG","==============start==============");
Log.e("TAG","name====="+name);
for (String string:mlist){
Log.e("TAG","text====="+string);
}
Log.e("TAG","==============end=================");
}
}
使用
WordDocument wordDocument = new WordDocument();
wordDocument.setName("张三");
wordDocument.addString("张三");
wordDocument.addString("张三");
wordDocument.addString("张三");
wordDocument.showDocument();
WordDocument clone = wordDocument.clone();
clone.showDocument();
clone.setName("李四");
clone.showDocument();
wordDocument.showDocument();
打印结果
四、浅拷贝和深拷贝
上述例子其实是一个浅拷贝,也称影子拷贝,这种拷贝并不是将原始数据字段拷贝了一份,只是引用了原始数据对象字段。只是指向了一个相同的内存地址。
有下面打印
WordDocument wordDocument = new WordDocument();
wordDocument.setName("张三");
wordDocument.addString("张三");
wordDocument.addString("张三");
wordDocument.addString("张三");
wordDocument.showDocument();
WordDocument clone = wordDocument.clone();
clone.showDocument();
clone.setName("李四");
clone.addString("李四");
clone.addString("李四");
clone.addString("李四");
clone.showDocument();
wordDocument.showDocument();
打印结果发现最后两次一样,修改一个另一个也变,所以这就是浅拷贝,解决可以采用深拷贝,改变一下方法如下
@Override
protected WordDocument clone() {
try {
WordDocument wordDocument= (WordDocument) super.clone();
wordDocument.name = this.name.clone();
wordDocument.mlist= (ArrayList<String>) this.mlist.clone();
return wordDocument;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
五、源码中原型设计模式
①ArrayList中的使用
上面例子可知ArrayList也有clone()方法,如下
@Override
public Object clone() {
try {
ArrayList<?> result = (ArrayList<?>) super.clone();
result.array = array.clone();
return result;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
其实该方法很简单先克隆本身再克隆对象中元素,为啥size没有克隆?因为size为整形,并不是一个对象,clone()为Object中方法,不是一个引用类型,是值类型,不需要克隆。
②Intent中的使用
Intent intent = new Intent();
intent.clone();
查看源码
@Override
public Object clone() {
return new Intent(this);
}
private Intent(Intent o, boolean all) {
this.mAction = o.mAction;
this.mData = o.mData;
this.mType = o.mType;
this.mPackage = o.mPackage;
this.mComponent = o.mComponent;
if (o.mCategories != null) {
this.mCategories = new ArraySet<String>(o.mCategories);
}
}