Android设计模式-3-原型模式
2020-12-29 本文已影响0人
今阳说
1. 定义:
用原型实例指定创建对象的种类,并通过拷贝这些原型对象创建新的对象,使程序更高效,关键词:样板,克隆,可定制
2. 适用场景:
- 类初始化需要消耗非常多的资源
- 类的创建复杂或构造耗时
- 保护性拷贝: 一个对象提供给其他对象访问,且各个调用者可能都会修改其值,可以使用原型模式拷贝多个对象供其使用,可以使用Cloneable接口
3. 优缺点:
- 优点:对内存中的二进制流的拷贝,比new性能好,尤其是循环体内产生大量对象时
- 缺点:其优点也是缺点,直接在内存中拷贝,不执行构造函数,少了约束
4. Android源码中的使用:
clone方法,如ArrayList的clone方法,Intent.clone()等
5. 实例演示
以文档的编辑还原为例,在编辑文档前会克隆一份副本,以做备份,对原稿的修改不会影响到该备份,在需要时可以还原,下面通过具体代码进行模拟
- 首先创建一个文档类WordDocument,它实现了Cloneable接口,主要由两个属性组成,文档的文本和插图的url集合,下面是具体的代码:
class WordDocument implements Cloneable {
//文本
private String text;
//图片列表
private ArrayList<String> images = new ArrayList<>();
public WordDocument() {
LjyLogUtil.i("WordDocument的构造函数");
}
@Override
protected WordDocument clone() {
WordDocument doc = null;
try {
doc = (WordDocument) super.clone();
doc.text = this.text;
//浅拷贝:
// doc.images = this.images;
//深拷贝
doc.images = (ArrayList<String>) this.images.clone();
} catch (CloneNotSupportedException e) {
LjyLogUtil.e(e.getLocalizedMessage());
}
return doc;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public ArrayList<String> getImages() {
return images;
}
public void setImages(ArrayList<String> images) {
this.images = images;
}
public void addImages(String img) {
this.images.add(img);
}
public void showDocument() {
LjyLogUtil.i("---------word content start-----------");
LjyLogUtil.i("text:" + text);
LjyLogUtil.i("images:");
for (String imgName : images) {
LjyLogUtil.i(imgName);
}
LjyLogUtil.i("---------word content end-----------");
}
}
上面代码中的clone()方法涉及到一个知识点,浅拷贝和深拷贝
- 浅拷贝是仅仅clone所要拷贝的对象,而不clone该对象所引用的对象,应为引用类型的变量只是持有被引用对象的内存地址,浅拷贝只是将内存地址拷贝一份,这样clone出来的多个对象及原对象中任何一个对该被引用对象进行修改都会影响到其他对象
- 深拷贝:将对象和它所引用的对象一起拷贝,对象间互不影响,但是相比于浅拷贝速度较慢并且花销较大。
- 接下来创建一个WordDocument对象,并进行clone(也就是原型模式所说的通过拷贝原型创建新的对象),而且运行程序后,通过打印的log证实,它们的修改是互不影响的
private void methodProtoPattern() {
//构建文档对象
WordDocument document = new WordDocument();
//编辑文档
document.setText("这是一篇文章啊");
document.addImages("img001");
document.addImages("img002");
document.addImages("img003");
//show
LjyLogUtil.i("document:");
document.showDocument();
//拷贝
WordDocument document2 = document.clone();
//show2
LjyLogUtil.i("clone document_2:");
document2.showDocument();
//编辑2
document2.setText("修改了文字啊");
//浅拷贝与深拷贝的区别,详勘clone方法
document2.addImages("image_004");
// document2.setImages(new ArrayList<String>());
//show
LjyLogUtil.i("document:");
document.showDocument();
//show2
LjyLogUtil.i("clone document_2:");
document2.showDocument();
}