Android开发中无处不在的设计模式——原型模式
2015-10-23 10:12
190 查看
不知不觉这个系列已经写了三篇了,其实很早之前就想写设计模式了,只不过怕自己误人子弟没有提笔去写。后来在实际开发中,发现设计模式可以让一个开发人员融会贯通所学的知识,为了进一步巩固自己,就写下了这一些列文章。前面介绍了三个模式。
Android开发中无处不在的设计模式——单例模式
Android开发中无处不在的设计模式——Builder模式
Android开发中无处不在的设计模式——观察者模式
本篇文章介绍的模式其实很简单,即原型模式,按照惯例,先看定义。
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
这是什么鬼哦,本宝宝看不懂!不必过度在意这些定义,自己心里明白就ok了。没代码你说个jb。
首先我们定义一个Person类
要实现原型模式,只需要按照下面的几个步骤去实现即可。
实现Cloneable接口
重写Object的clone方法
实现clone方法中的拷贝逻辑
测试一下
输出结果如下
Person{name=’张三’, age=18, height=178.0, weight=65.0}
Person{name=’张三’, age=18, height=178.0, weight=65.0}
Person{name=’张三’, age=18, height=178.0, weight=65.0}
Person{name=’李四’, age=18, height=178.0, weight=65.0}
试想一下,两个不同的人,除了姓名不一样,其他三个属性都一样,用原型模式进行拷贝就会显得异常简单,这也是原型模式的应用场景之一。
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
但是假设Person类里还有一个属性叫兴趣爱好,是一个List集合,就像这样子
在进行拷贝的时候要格外注意,如果你直接按之前的代码那样拷贝
会带来一个问题
使用测试代码进行测试
我们拷贝了一个对象,并添加了一个兴趣爱好进去,看下打印结果
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑, 游泳]}
Person{name=’李四’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑, 游泳]}
你会发现原来的对象的hobby也发生了变换。
其实导致这个问题的本质原因是我们只进行了浅拷贝,也就是只拷贝了引用,最终两个对象指向的引用是同一个,一个发生变化另一个也会发生变换,显然解决方法就是使用深拷贝。
注意person.hobbies=(ArrayList)this.hobbies.clone();,不再是直接引用而是进行了一份拷贝。再运行一下,就会发现原来的对象不会再发生变化了。
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’李四’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑, 游泳]}
其实有时候我们会更多的看到原型模式的另一种写法。
在clone函数里调用构造函数,构造函数的入参是该类对象。
在构造函数中完成拷贝逻辑
其实都差不多,只是写法不一样。
现在来挖挖android中的原型模式。
先看Bundle类,该类实现了Cloneable接口
然后是Intent类,该类也实现了Cloneable接口
用法也显得十分简单,一旦我们要用的Intent与现有的一个Intent很多东西都是一样的,那我们就可以直接拷贝现有的Intent,再修改不同的地方,便可以直接使用。
网络请求中一个最常见的开源库OkHttp中,也应用了原型模式。它就在OkHttpClient这个类中,它实现了Cloneable接口
正如开头的注释Returns a shallow copy of this OkHttpClient,该clone方法返回了一个当前对象的深拷贝对象。
至于其他框架中的原型模式,请读者自行发现。
Android开发中无处不在的设计模式——单例模式
Android开发中无处不在的设计模式——Builder模式
Android开发中无处不在的设计模式——观察者模式
本篇文章介绍的模式其实很简单,即原型模式,按照惯例,先看定义。
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
这是什么鬼哦,本宝宝看不懂!不必过度在意这些定义,自己心里明白就ok了。没代码你说个jb。
首先我们定义一个Person类
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Person{ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String name; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> age; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> height; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> weight; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Person</span>(){ } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">getName</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> name; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setName</span>(String name) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.name = name; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">getAge</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> age; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setAge</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> age) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.age = age; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> <span class="hljs-title" style="box-sizing: border-box;">getHeight</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> height; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setHeight</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> height) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.height = height; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> <span class="hljs-title" style="box-sizing: border-box;">getWeight</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> weight; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setWeight</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> weight) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.weight = weight; } @Override <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> String <span class="hljs-title" style="box-sizing: border-box;">toString</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Person{"</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"name='"</span> + name + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'\''</span> + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">", age="</span> + age + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">", height="</span> + height + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">", weight="</span> + weight + <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'}'</span>; } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li></ul>
要实现原型模式,只需要按照下面的几个步骤去实现即可。
实现Cloneable接口
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Person</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Cloneable</span>{</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>
重写Object的clone方法
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">clone</span>(){ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
实现clone方法中的拷贝逻辑
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">clone</span>(){ Person person=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> { person=(Person)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.clone(); person.name=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.name; person.weight=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.weight; person.height=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.height; person.age=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.age; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (CloneNotSupportedException e) { e.printStackTrace(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> person; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li></ul>
测试一下
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> Main { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">main</span>(String [] args){ Person p=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Person(); p.setAge(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>); p.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"张三"</span>); p.setHeight(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">178</span>); p.setWeight(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">65</span>); System.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">out</span>.println(p); Person p1= (Person) p.clone(); System.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">out</span>.println(p1); p1.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"李四"</span>); System.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">out</span>.println(p); System.<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">out</span>.println(p1); } } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li></ul>
输出结果如下
Person{name=’张三’, age=18, height=178.0, weight=65.0}
Person{name=’张三’, age=18, height=178.0, weight=65.0}
Person{name=’张三’, age=18, height=178.0, weight=65.0}
Person{name=’李四’, age=18, height=178.0, weight=65.0}
试想一下,两个不同的人,除了姓名不一样,其他三个属性都一样,用原型模式进行拷贝就会显得异常简单,这也是原型模式的应用场景之一。
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。
但是假设Person类里还有一个属性叫兴趣爱好,是一个List集合,就像这样子
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> ArrayList<String> hobbies=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<String>(); <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> ArrayList<String> <span class="hljs-title" style="box-sizing: border-box;">getHobbies</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> hobbies; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">setHobbies</span>(ArrayList<String> hobbies) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.hobbies = hobbies; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
在进行拷贝的时候要格外注意,如果你直接按之前的代码那样拷贝
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">clone</span>(){ Person person=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> { person=(Person)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.clone(); person.name=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.name; person.weight=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.weight; person.height=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.height; person.age=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.age; person.hobbies=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.hobbies; } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (CloneNotSupportedException e) { e.printStackTrace(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> person; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li></ul>
会带来一个问题
使用测试代码进行测试
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">public class Main { public static void main(String [] args){ Person p=new Person()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> p<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setAge</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">18</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> p<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setName</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"张三"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> p<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setHeight</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">178</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> p<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setWeight</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">65</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> ArrayList <String> hobbies=new ArrayList<String>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> hobbies<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"篮球"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> hobbies<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"编程"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> hobbies<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"长跑"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> p<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setHobbies</span>(hobbies)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> System<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.out</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.println</span>(p)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> Person p1= (Person) p<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.clone</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> System<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.out</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.println</span>(p1)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> p1<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setName</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"李四"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> p1<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getHobbies</span>()<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.add</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"游泳"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> System<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.out</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.println</span>(p)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> System<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.out</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.println</span>(p1)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>
我们拷贝了一个对象,并添加了一个兴趣爱好进去,看下打印结果
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑, 游泳]}
Person{name=’李四’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑, 游泳]}
你会发现原来的对象的hobby也发生了变换。
其实导致这个问题的本质原因是我们只进行了浅拷贝,也就是只拷贝了引用,最终两个对象指向的引用是同一个,一个发生变化另一个也会发生变换,显然解决方法就是使用深拷贝。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">clone</span>(){ Person person=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> { person=(Person)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>.clone(); person.name=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.name; person.weight=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.weight; person.height=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.height; person.age=<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.age; person.hobbies=(ArrayList<String>)<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.hobbies.clone(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (CloneNotSupportedException e) { e.printStackTrace(); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> person; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li></ul>
注意person.hobbies=(ArrayList)this.hobbies.clone();,不再是直接引用而是进行了一份拷贝。再运行一下,就会发现原来的对象不会再发生变化了。
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’张三’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑]}
Person{name=’李四’, age=18, height=178.0, weight=65.0, hobbies=[篮球, 编程, 长跑, 游泳]}
其实有时候我们会更多的看到原型模式的另一种写法。
在clone函数里调用构造函数,构造函数的入参是该类对象。
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">clone</span>(){ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Person(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>); } </code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>
在构造函数中完成拷贝逻辑
<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Person</span>(Person person){ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.name=person.name; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.weight=person.weight; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.height=person.height; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.age=person.age; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.hobbies= <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<String>(hobbies); }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li></ul>
其实都差不多,只是写法不一样。
现在来挖挖android中的原型模式。
先看Bundle类,该类实现了Cloneable接口
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">clone</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Bundle(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Bundle</span>(Bundle b) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">super</span>(b); mHasFds = b.mHasFds; mFdsKnown = b.mFdsKnown; }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li></ul>
然后是Intent类,该类也实现了Cloneable接口
<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object <span class="hljs-title" style="box-sizing: border-box;">clone</span>() { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Intent(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-title" style="box-sizing: border-box;">Intent</span>(Intent o) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mAction = o.mAction; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mData = o.mData; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mType = o.mType; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mPackage = o.mPackage; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mComponent = o.mComponent; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mFlags = o.mFlags; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mContentUserHint = o.mContentUserHint; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (o.mCategories != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mCategories = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArraySet<String>(o.mCategories); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (o.mExtras != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mExtras = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Bundle(o.mExtras); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (o.mSourceBounds != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mSourceBounds = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Rect(o.mSourceBounds); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (o.mSelector != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mSelector = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Intent(o.mSelector); } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (o.mClipData != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">this</span>.mClipData = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ClipData(o.mClipData); } }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li></ul>
用法也显得十分简单,一旦我们要用的Intent与现有的一个Intent很多东西都是一样的,那我们就可以直接拷贝现有的Intent,再修改不同的地方,便可以直接使用。
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">Uri uri = Uri<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.parse</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"smsto:10086"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; </span> Intent shareIntent = new Intent(Intent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.ACTION</span>_SENDTO, uri)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; </span> shareIntent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.putExtra</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"sms_body"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"hello"</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">; </span> Intent intent = (Intent)shareIntent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.clone</span>() <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> startActivity(intent)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>
网络请求中一个最常见的开源库OkHttp中,也应用了原型模式。它就在OkHttpClient这个类中,它实现了Cloneable接口
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/** Returns a shallow copy of this OkHttpClient. */</span> @Override public OkHttpClient clone() { return new OkHttpClient(this)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> } private OkHttpClient(OkHttpClient okHttpClient) { this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.routeDatabase</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.routeDatabase</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.dispatcher</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.dispatcher</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.proxy</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.proxy</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.protocols</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.protocols</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.connectionSpecs</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.connectionSpecs</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.interceptors</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addAll</span>(okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.interceptors</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.networkInterceptors</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.addAll</span>(okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.networkInterceptors</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.proxySelector</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.proxySelector</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cookieHandler</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cookieHandler</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cache</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.cache</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.internalCache</span> = cache != null ? cache<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.internalCache</span> : okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.internalCache</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.socketFactory</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.socketFactory</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sslSocketFactory</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sslSocketFactory</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.hostnameVerifier</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.hostnameVerifier</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.certificatePinner</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.certificatePinner</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.authenticator</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.authenticator</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.connectionPool</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.connectionPool</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.network</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.network</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.followSslRedirects</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.followSslRedirects</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.followRedirects</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.followRedirects</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.retryOnConnectionFailure</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.retryOnConnectionFailure</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.connectTimeout</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.connectTimeout</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.readTimeout</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.readTimeout</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> this<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.writeTimeout</span> = okHttpClient<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.writeTimeout</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li></ul>
正如开头的注释Returns a shallow copy of this OkHttpClient,该clone方法返回了一个当前对象的深拷贝对象。
至于其他框架中的原型模式,请读者自行发现。
相关文章推荐
- Android官方提供的支持不同屏幕大小的全部方法
- Android开发总结笔记 四大组件之ContentPovider(下) 1-2-9
- 【Android应用开发】Android Studio 错误集锦 -- 将所有的 AS 错误集合到本文
- 【Android应用开发】Android Studio 错误集锦 -- 将所有的 AS 错误集合到本文
- android比较时间
- Android 线程池及多线程下载,Progressbar动态更新以及文件保存sd卡
- Android 线程池及多线程下载,Progressbar动态更新以及文件保存sd卡
- AndroidScreenSlide项目切换view动画效果《IT蓝豹》
- Android--Activity简介及生命周期
- AndroidVideoPlayer在线播放视频
- android 动画实现(一)Tween动画
- Android 三大图片缓存原理、特性对比
- Android API Level最新版本到6.0Platform Codenames, Versions, API Levels, and NDK Releases
- Android Fragment应用实战
- android ListViewA-Z字母索引
- android里面播放声音的方法---执行某项操作发出滴的一声
- android.content.ActivityNotFoundException: Unable to find explicit activity class have you declared this activity in your AndroidManifest.xml?
- Android Gradle实用技巧——APK文件名中加上SVN版本号,日期等
- Android -- Looper.prepare()和Looper.loop() —深入版
- Activity生命周期的自我理解