设计模式之原型模式
来源:互联网 发布:婚纱照排版台词 知乎 编辑:程序博客网 时间:2024/06/07 21:56
定义:根据现有的对象进行克隆产生一个新的对象。当直接进行对象创建性能消耗比较大的情形之下,即可用使用原型模式。 比如在创建一对象的时候,需要通过操作数据库或者文件才能被创建。这种情况之下我们就可以对已有的对象进行缓存,然后在下次创建对象的时候返回,从而减少数据库或者文件的操作。
具体结构图(图片摘自百度百科)
需要的角色:客户端(Client):具体调用者类。抽象的原型类(Prototype): 实现Cloneable接口。 方便扩展。具体的原型类(ConcretePrototype):客服端需要的对象, 重写Object的clone()方法,进行对象的克隆。
使用场景: 1、类初始化需要消耗很大的资源。 2、对性能和安全有较高的要求。 3、创建一个对象需要大量的数据准备和访问权限。 4、对象可能被多个使用者修改。优点: 1、对于需要产生大量对象的场景, 使用clone大大提高性能。 2、直接从内存中拷贝, 跳过了构造函数的约束。缺点: 1、必须实现Cloneable接口。 2、对于已经封装好的类不容易实现。 3、逃避了构造函数的约束。使用示例: 1、细胞分裂。 2、游戏中大量相同对象(打飞机游戏中的子弹)。注意事项: 1、原型模式是通过直接在内存中进行对象克隆的,因此不会执行构造方法,而且访问权限也是无效的。原型模式和单例模式是冲突的。 2、clone()方法只会对基本数据类型(包括String)进行拷贝, 对于数组、map、自定义对象等不会进行拷贝,如果需要,则需要进行深度拷贝(对这些数据另行进行拷贝)。 3、必须实现Cloneable 接口,不然会抛出CloneNotSupportedException异常。 4、clone()的访问权限为protected, 需要修改为public,不然在客户端没法调用。
示例代码:
具体原型类(这只是简单测试, 如果需要扩展,可以定义基类)
public class Mobile implements Cloneable { private static final String TAG = "Clone"; private String name; private String brand; public Mobile() { Log.i(TAG, "Mobile: 构造方法被调用啦"); } public void setName(String name) { this.name = name; } public void setBrand(String brand) { this.brand = brand; } @Override public Mobile clone() throws CloneNotSupportedException { return (Mobile) super.clone(); } @Override public String toString() { return "name = " + name + " , brand = " + brand ; }}客户端测试代码:
Mobile mobile = new Mobile(); mobile.setName("红米note4"); mobile.setBrand("小米"); try { Mobile mobile1 = mobile.clone(); mobile1.setName("vivox9"); mobile1.setBrand("vivo"); Mobile mobile2 = mobile.clone(); mobile2.setBrand("乐视"); mobile2.setName("乐视s3"); Log.i(TAG, "cloneMobile: " + mobile.toString()); Log.i(TAG, "cloneMobile: " + mobile1.toString()); Log.i(TAG, "cloneMobile: " + mobile2.toString()); } catch (CloneNotSupportedException e) { e.printStackTrace(); }测试结果: 从输出的结果可以看出, 构造方法值被执行一次,说明后面两个对象都是通过clone实现的,从而验证了clone不调用构造方法的说法。
上面示例代码中的对象的属性采用的是String, 下面我们换成自定义对象试试:
自定义属性类:
public class Brand { private String name; private String sysVersion; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSysVersion() { return sysVersion; } public void setSysVersion(String sysVersion) { this.sysVersion = sysVersion; } @Override public String toString() { return "name = " + name + ", sysVersion = " + sysVersion ; }}具体原型类中代码修改:
public class Mobile implements Cloneable { private static final String TAG = "Clone"; private String name; private Brand brand; public Mobile() { Log.i(TAG, "Mobile: 构造方法被调用啦"); this.brand = new Brand(); } public void setName(String name) { this.name = name; } public void setBrand(String name, String sysVersion) { this.brand.setName(name); this.brand.setSysVersion(sysVersion); } @Override public Mobile clone() throws CloneNotSupportedException { return (Mobile) super.clone(); } @Override public String toString() { return "name = " + name + " , brand = " + brand ; }}客户端测试代码:
Mobile mobile = new Mobile(); mobile.setName("红米note4"); mobile.setBrand("小米", "6.0"); try { Mobile mobile1 = mobile.clone(); mobile1.setName("vivox9"); mobile1.setBrand("vivo", "6.0"); Mobile mobile2 = mobile.clone(); mobile2.setBrand("乐视", "5.0"); mobile2.setName("乐视s3"); Log.i(TAG, "cloneMobile: " + mobile.toString()); Log.i(TAG, "cloneMobile: " + mobile1.toString()); Log.i(TAG, "cloneMobile: " + mobile2.toString()); } catch (CloneNotSupportedException e) { e.printStackTrace(); }测试结果:通过测试结果可以看出, 自定义属性并没有被clone,只是后面的赋值替换前面的赋值,从而以验证了clone()方法只能对基本数据类型以及String类型进行clone,而不能对数组、map、自定义数据类型进行clone(这就是常说的浅克隆)。
那怎样能实现对自定义数据类型进行拷贝呢? 实现很简单,进行深度克隆即可,即对自定义数据类型进行单独克隆,示例代码如下:
自定义数据类: 需要实现Cloneable接口, 重写clone()方法。
public class Brand implements Cloneable { private String name; private String sysVersion; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSysVersion() { return sysVersion; } public void setSysVersion(String sysVersion) { this.sysVersion = sysVersion; } @Override public Brand clone() throws CloneNotSupportedException { return (Brand) super.clone(); } @Override public String toString() { return "name = " + name + ", sysVersion = " + sysVersion ; }}具体原型类中代码
public class Mobile implements Cloneable { private static final String TAG = "Clone"; private String name; private Brand brand; public Mobile() { Log.i(TAG, "Mobile: 构造方法被调用啦"); this.brand = new Brand(); } public void setName(String name) { this.name = name; } public void setBrand(String name, String sysVersion) { this.brand.setName(name); this.brand.setSysVersion(sysVersion); } @Override public Mobile clone() throws CloneNotSupportedException { Mobile mobile = (Mobile) super.clone(); mobile.brand = this.brand.clone(); //对引用对象进行深度clone return mobile; } @Override public String toString() { return "name = " + name + " , brand = " + brand ; }}客户端测试代码:
Mobile mobile = new Mobile(); mobile.setName("红米note4"); mobile.setBrand("小米", "6.0"); try { Mobile mobile1 = mobile.clone(); mobile1.setName("vivox9"); mobile1.setBrand("vivo", "6.0"); Mobile mobile2 = mobile.clone(); mobile2.setBrand("乐视", "5.0"); mobile2.setName("乐视s3"); Log.i(TAG, "cloneMobile: " + mobile.toString()); Log.i(TAG, "cloneMobile: " + mobile1.toString()); Log.i(TAG, "cloneMobile: " + mobile2.toString()); } catch (CloneNotSupportedException e) { e.printStackTrace(); }测试结果:从测试结果看出,我们实现了深度克隆。
阅读全文
0 0
- 设计模式之原型
- 设计模式之原型
- 设计模式 之 原型
- 设计模式之原型
- 设计模式之原型
- 设计模式之原型模式
- 设计模式之原型模式
- 设计模式之-原型模式
- 设计模式之 原型模式
- 设计模式之原型模式
- 设计模式之原型模式
- 设计模式之原型模式
- 设计模式之原型模式
- 设计模式之原型模式
- 设计模式之--原型模式
- 设计模式之原型模式
- 设计模式之原型模式
- 设计模式之原型模式
- installation failed with message invalid file
- extjs 鼠标悬停显示文本
- 短信链接唤起app
- [机器学习] 决策树
- 基于ODPS的SQL语句
- 设计模式之原型模式
- Lorg/apache/ws/commons/schema/XmlSchema;
- Dubbo-Admin管理平台和Zookeeper注册中心的搭建
- exe4j生成的exe反编译成java代码
- 挑战4道Java试题
- WebView 如何自定义自己的右键菜单?
- 使用setInterval对ajax请求做轮询
- 同步与异步、阻塞与非阻塞
- CSDN--字体颜色--markdown