05
2017
10

Android设计模式-原型模式

好久没有写新的文章了,趁这国庆没什么事,来理一理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

上一篇:【Android】の基础——ListView和RecyclerView缓存机制 下一篇:Android自定义View与添加点击事件