好久没有写新的文章了,趁这国庆没什么事,来理一理Android的设计模式。
感觉设计模式很多都应用于Android的源码当中,而且很大一部分都是使用Java的面向接口编程思想。学习Android的设计模式,对于面向接口的编程思想很有帮助,可以帮助理解Android的源码,还是很有用的。那我们就从Android的编程模式的创建模型来学习。
原型模式挺简单的,实用性也比较高,我们先看下他的定义:
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
啊,好吧。其实这个模式主要就是拷贝对象,重写一个clone();方法。这个模式:主要作用就是提高对象创建的效率。分为:浅拷贝和深度拷贝
浅拷贝:在pojo中实现cloneable接口,然后覆写clone();方法。在代码中调用clone();方法就可以了。
public class CloneBean implements Cloneable{
private String str;
private TestBean testBean;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public TestBean getTestBean() {
return testBean;
}
public void setTestBean(TestBean testBean) {
this.testBean = testBean;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}}
然后在代码中调用clone();方法
那我们来看下浅拷贝的实现状况:
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
CloneBean cloneBean = new CloneBean();
cloneBean.setStr("aaa");
cloneBean.setTestBean(new TestBean("bbb"));
try {
CloneBean cloneBean2 = (CloneBean) cloneBean.clone();
System.out.println(cloneBean2.getStr()+"---"+cloneBean2.getTestBean().getA());
System.out.println(cloneBean2.toString()+"---"+cloneBean.toString());
System.out.println(cloneBean2.getTestBean().toString()+"---"+cloneBean.getTestBean().toString());
cloneBean.setStr("ccc");
cloneBean.getTestBean().setA("ddd");
System.out.println(cloneBean2.getStr()+"---"+cloneBean.getStr());
System.out.println(cloneBean2.getTestBean().getA()+"---"+cloneBean.getTestBean().getA());
System.out.println("==========================================================");
CloneBean cloneBean3 = cloneBean;
System.out.println(cloneBean3.getStr()+"---"+cloneBean2.getTestBean().getA());
System.out.println(cloneBean3.toString()+"---"+cloneBean.toString());
System.out.println(cloneBean3.getTestBean().toString()+"---"+cloneBean.getTestBean().toString());
cloneBean.setStr("eee");
cloneBean.getTestBean().setA("fff");
System.out.println(cloneBean3.getStr()+"---"+cloneBean.getStr());
System.out.println(cloneBean3.getTestBean().getA()+"---"+cloneBean.getTestBean().getA());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
这个是原型模式的测试代码
aaa---bbb
com.example.mytouchapp.CloneBean@1376c05c---com.example.mytouchapp.CloneBean@51521cc1
com.example.mytouchapp.TestBean@1b4fb997---com.example.mytouchapp.TestBean@1b4fb997
aaa---ccc
ddd---ddd
==========================================================
ccc---ddd
com.example.mytouchapp.CloneBean@51521cc1---com.example.mytouchapp.CloneBean@51521cc1
com.example.mytouchapp.TestBean@1b4fb997---com.example.mytouchapp.TestBean@1b4fb997
eee---eee
可以看到被复制的对象cloneBean2的变量的值跟cloneBean的是是一模一样的。而且cloneBean内的对象TestBean和cloneBean2的居然连内存地址都一模一样。这就意味着:浅拷贝的时候,被拷贝对象内里面如果有也有对象存在,那么这个对象并不在拷贝范围内,这个内部的对象只要改变,cloneBean和cloneBean2的TestBean都会发生改变。这个时候,就需要用深度拷贝了,将对象内部的变量全部都拷贝一遍。“
在原来cloneBean的基础上,重写clone方法:
i
@Override
protected Object clone() throws CloneNotSupportedException {
CloneBean doc = (CloneBean) super.clone();
//如果要深度拷贝
doc.str = this.str;
doc.testBean = (TestBean) this.testBean.clone();
return doc;
}
实际上就相当于是把整个对象迭代一遍,将所有对象的变量重新拷贝一遍。看看打印输出:
aaa---bbb
com.example.mytouchapp.CloneBean@1376c05c---com.example.mytouchapp.CloneBean@51521cc1
com.example.mytouchapp.TestBean@1b4fb997---com.example.mytouchapp.TestBean@deb6432
aaa---ccc
bbb---ddd
==========================================================
ccc---bbb
com.example.mytouchapp.CloneBean@51521cc1---com.example.mytouchapp.CloneBean@51521cc1
com.example.mytouchapp.TestBean@deb6432---com.example.mytouchapp.TestBean@deb6432
eee---eee
fff---fff
这个时候两个testBean的内存地址都不一样,说明拷贝成功了。
原型模式测试代码github: https://github.com/zhoukeda/PrototypeDemo