概述
原型模式是一个创建型的模式。该模式有一个样板实例,用户从这个样板对象中复制出一个内部属性一致的对象,这个过程也就是俗称的“克隆”。被复制的实例就是所称的“原型”。
原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象
使用场景
类初始化需要消耗非常多的资源,包括数据、硬件资源等,通过原型拷贝避免这些消耗
通过new产生一个对象需要非常繁琐的数据准备或访问权限。这时可以使用原型拷贝
一个对象需要提供给其他对象调用者使用,而且各个调用者都需要修改其值,可以考虑通过原型模式拷贝多个对象供调用者使用,即保护性拷贝
原型模式的简单实现
通过实现Cloneable接口:
首先创建一个文档对象,即WordDocument,这个文档中含有文字和图片,编辑时在文档副本上修改。
public class WordDocument implements Cloneable {
private String mText;
private ArrayList<String> mImages = new ArrayList<>();
public WordDocument() {
System.out.println("---------- WordDocument构造函数 -------------");
}
@Override
protected WordDocument clone() {
try {
WordDocument doc = (WordDocument) super.clone();
doc.mText = this.mText;
doc.mImages = this.mImages; // 浅拷贝
doc.mImages = (ArrayList<String>) mImages.clone(); // 深拷贝,引用类型
return doc;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public String getmText() {
return mText;
}
public void setmText(String mText) {
this.mText = mText;
}
public List<String> getmImages() {
return mImages;
}
public void addImage(String img) {
this.mImages.add(img);
}
}
浅拷贝: 也称影子拷贝,副本并不是将原型所有字段都重新构造,而是引用。
深拷贝: 即拷贝对象时,对引用型的字段也要采用拷贝形式,并不是单纯的引用
需要拷贝时调用clone()
WordDocument originDoc = new WordDocument();
originDoc.setmText("这是一篇文章");
originDoc.addImage("图片1");
originDoc.addImage("图片2");
WordDocument doc = originDoc.clone();
Android中的原型模式
- ArrayList:
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
- Intent:
@Override
public Object clone() {
return new Intent(this);
}
- …………
总结
使用原型模式可以解决构建复杂对象的资源消耗问题,能够在某些场景提升创建对象的效率。还有一个重要用途就是保护性拷贝,也就是某个对象对外可能是只读的,为了防止外部对这个只读对象修改,通常可以返回一个对象拷贝的形式实现只读的限制。
注意浅拷贝、深拷贝的区别
优点: 原型模式是在内存中二进制流的拷贝,要比直接new一个对象性能好很多,特别是在一个循环体内产生大量的对象时,原型模型可以更好地体现其优点
缺点: 直接在内存中拷贝,构造函数是不会执行的,实际开发要考虑这个潜在问题