2019独角兽企业重金招聘Python工程师标准>>>

1. 原型模式介绍

原型模式是一个创建型的模式。原型二字表明了该模式应该有一个样板实例,用户从这个样板对象中复制出一个内部属性一致的对象,这个过程就是我们俗称的“克隆”。

2. 使用场景

(1) 类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免这些消耗。

(2) 通过new产生一个对象需要非常繁琐的数据准备或访问权限,可以使用原型模式。

(3) 一个对象需要提供个其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝。

个人理解,原型模式,其实就是利用Java提供的克隆Cloneable生成对象的过程。

注意:通过Cloneable接口的原型模式并不一定比通过new操作快,不过,如果对象包含大量数据需要赋值,使用原型模式可以减少大量代码。

3. 浅拷贝和深拷贝

(1) 浅拷贝,也称为影子拷贝,这份拷贝实际上并不是将原始对象的所有字段都重新构造一份,而是使用的引用方式。即两个对象指向同一个地址。

public class WordDoc implements Cloneable {private int mSize;private String mText;private ArrayList<String> mImages = new ArrayList<String>();@Overrideprotected WordDoc clone() {try {WordDoc doc = (WordDoc) super.clone();doc.mText = this.mText;doc.mImages = this.mImages;return doc;} catch (Exception e) {}return null;}
}

可以看到,这种方式,doc.mImages = this.mImages使用的是引用方式

(2) 深拷贝,即在拷贝对象时,对于引用型的字段也要采用拷贝的形式。

doc.mImages = (ArrayList<String) this.mImages.clone()

public class WordDoc implements Cloneable {private int mSize;private String mText;private ArrayList<String> mImages = new ArrayList<String>();@Overrideprotected WordDoc clone() {try {WordDoc doc = (WordDoc) super.clone();doc.mText = this.mText;doc.mImages = (ArrayList<String) this.mImages.clone();return doc;} catch (Exception e) {}return null;}
}

这种方式,要求字段的类也要实现Cloneable接口,即是可以clone的。

Java基本类型int、byte、boolean不需要进行clone。

查看ArrayList源码,可以看到。

public class ArrayList<E> extends AbstractList<E> implements Cloneable, Serializable, RandomAccess {int size;transient Object[] array;@Overridepublic Object clone() {try {ArrayList<?> result = (ArrayList<?>) super.clone();result.array = array.clone();return result;} catch (CloneNotSupportException e) {throw new AssertionError();}}
}

注意:通过clone方法实现对象克隆,但这个方法并不是Cloneable接口中的,而是Object中的方法。Cloneable也是一个标识接口,它表明这个类的对象是可以拷贝的。如果没有实现Cloneable接口却调用了clone()函数将抛出异常。

还要注意:通过clone拷贝对象时,并不会执行构造函数。

4. 原型模式实战

在开发中,有时会满足一些需求,就是有的对象中的内容允许客户端程序读取,而不允许修改。

public class User {public int age;public String name;public String address;
}
// 登录接口
public interface Login {void login();
}
// 登录实现
public class LoginImpl implements Login {@Overridepublic void login() {// 登录到服务器,获取用户信息User loginUser = new User();// 将服务器返回的完整信息设置给loginUser对象loginUser.age = 22;loginUser.name = "Mr.Simple";login.address = "北京市";// 登录完后将用户信息设置到Session中LoginSession.getLoginSession().setLoginedUser(loginUser);}
}
// 登录session
public class LoginSession {static LoginSession sLoginSession = null;private User loginUser;private LoginSession() {}public static LoginSession getLoginSession() {if (sLoginSession == null) {sLoginSession = new LoginSession();}return sLoginSession;}// 设置登录的用户信息,不对外开放void setLoginedUser(User user) {loginUser = user;}public User getLoginedUser() {return loginedUser;}
}

问题:上面的getLoginedUser()方法,可以直接获取User对象,并更改对象内容,且会影响Session中的原对象内容。这样,客户端程序就不通过LoginSession设置用户信息了。

利用原型模式实现保护性拷贝即可避免这种问题

public class LoginSession {......public User getLoginedUser() {return loginedUser.clone();}
}

这种方式获取的是一个拷贝对象,修改拷贝对象也不会影响最初的登录用户对象。

转载于:https://my.oschina.net/android520/blog/833624

Android源码设计模式解析与实战(四)相关推荐

  1. 《Android源码设计模式解析与实战》读书笔记(十三)

    第十三章.备忘录模式 备忘录模式是一种行为模式,该模式用于保存对象当前的状态,并且在之后可以再次恢复到此状态,有点像是我们平常说的"后悔药". 1.定义 在不破坏封闭的前提下,捕获 ...

  2. 《Android源码设计模式解析与实战》读书笔记(十四)

    第十四章.迭代器模式 迭代器模式,又叫做游标模式,是行为型设计模式之一.我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法,让使用容器的人自己去实现去吧. ...

  3. 《Android源码设计模式解析与实战》读书笔记(二十四)

    第二十四章.桥接模式 桥接模式也称为桥梁模式,是结构型设计模式之一.桥接模式中体现了"单一职责原则"."开闭原则"."里氏替换原则".&qu ...

  4. 《Android源码设计模式解析与实战》读书笔记(十七)

    第十七章.中介者模式 中介者模式也称为调解者模式或调停者模式,是一种行为型模式. 1.定义 中介者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用.从而使它们可以松散耦合.当某些对象之 ...

  5. 《Android源码设计模式解析与实战》读书笔记(十二)

    第十二章.观察者模式 观察者模式是一个使用率非常高的模式,它最常用在GUI系统.订阅–发布系统.因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小,甚至做到毫无依赖. ...

  6. 《Android源码设计模式解析与实战》读书笔记(十)

    第十章.解释器模式 解释器模式是一种用的比较少的行为型模式,其提供了一种解释语言的语法或表达式的方式.但是它的使用场景确实很广泛,只是因为我们自己很少回去构造一个语言的文法,所以使用较少. 1.定义 ...

  7. 《Android源码设计模式解析与实战》读书笔记(二十一)

    第二十一章.装饰模式 装饰模式也称为包装模式,是结构型设计模式之一.装饰模式是一种用于替代继承技术的一种方案. 1.定义 动态的给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类更为灵 ...

  8. 《Android源码设计模式解析与实战》读书笔记(十一)

    第十一章.命令模式 命令模式是行为型模式之一.总体来说并不难理解,只是比较繁琐,他会将简单的调用关系解耦成多个部分,增加类的复杂度,但是即便如此,命令模式的结构依然清晰. 1.定义 将一个请求封装成一 ...

  9. 《Android源码设计模式解析与实战》读书笔记(十九)

    第十九章.组合模式 组合模式也称为部分-整体模式,结构型设计模式之一. 1.定义 将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性. ...

最新文章

  1. SQL语法之基础查询(进阶1)and条件查询(进阶2)
  2. 【深度学习】短袖短裤识别算法冠军方案总结
  3. How where used list in SAP GUI is implemented
  4. python数据分类方法_Python数据挖掘—分类—贝叶斯分类
  5. leetcode刷题——415. 字符串相加
  6. SVN clean失败解决方法
  7. JS中Null与Undefined的区别
  8. 解决Ubuntu18无法连接Airpods、蓝牙耳机的问题
  9. 手机型号大全_2000-2500元智能手机最全导购推荐(学生党手机必看)-2020年12月更新...
  10. 干货 | 扫了那么多二维码,15款工具打造你的专属二维码
  11. matlab2018在图片上添加文字并保存且图片没有白边
  12. 圆周率一千万亿位_圆周率一千位
  13. 华为服务器centos安装系统,华为裸金属服务器泰山200安装Centos7图文解析
  14. 关于睡眠你应该知道的十件事
  15. 我成功转型大厂数据分析师后,总结了这些经验…
  16. JavaScript 无法获取响应 header 的 Content-Disposition 字段
  17. Closing curly brace does not appear on the same line as the subsequent block - 代码规范性问题
  18. 地狱模式的居转户记录06
  19. pandas交叉表与透视表pd.crosstab()和pd.pivot_table()函数详解
  20. h7的HAL 1.8.0版本库的RTC时钟没起振 死循环 无法退出

热门文章

  1. linux查看文件时显示行号,linux中查看文件时显示行号
  2. ipad safari php readfile mp4,php – 在mac上的safari中没有加载Wav文件
  3. vue 地图使用navigator_9 个实验 + 3 个项目,带你入门 Vue.js 3 !
  4. 9个元素换6次达到排序序列_全面讲解十大经典排序算法(Python实现)
  5. html中图片显示、隐藏
  6. 在a标签中添加点击事件
  7. Android中通过反射和getResource()得到id的方式去改变View的显示效果
  8. Linux文本文件与Windows下的格式转换
  9. TensorFlow可以“预装”数据集了,新功能Datasets出炉
  10. 无人车是怎样一步步学会开车的? | 自动驾驶科普