java设计模式之原型模式
来源:互联网 发布:云霄网络 编辑:程序博客网 时间:2024/05/20 09:06
Prototype原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。—百度百科。
原型模式又称为克隆模式,可以分为浅克隆和深克隆,下面分别用代码来实现这两种不同类型的克隆方式。
浅克隆:
package cn.zzit.prototype;import java.util.Date;public class Sheep implements Cloneable { private String name; private Date birthday; public Sheep(String name, Date birthday) { super(); this.name = name; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
测试代码:
package cn.zzit.prototype;import java.util.Date;/** * 测试浅复制 * @author yufu * */public class Client { public static void main(String[] args) throws Exception { Date date=new Date(12366521155L); Sheep s1=new Sheep("多利羊",date); Sheep s2=(Sheep) s1.clone(); System.out.println("s1对象:"+s1); System.out.println("s1对象的名字:"+s1.getName()); System.out.println("s1对象的生日:"+s1.getBirthday()); System.out.println("克隆的s2对象:"+s2); System.out.println("克隆的s2对象:"+s2.getName()); System.out.println("克隆的s2对象:"+s2.getBirthday()); }}
输出结果:
s1对象:cn.zzit.prototype.Sheep@15db9742s1对象的名字:多利羊s1对象的生日:Sun May 24 11:08:41 CST 1970克隆的s2对象:cn.zzit.prototype.Sheep@5c647e05克隆的s2对象:多利羊克隆的s2对象:Sun May 24 11:08:41 CST 1970
由输出结果我们可以看出,s1和s2虽然是不同的对象,但是他们的属性值是一样的,这样也就实现了s1对象的克隆。
深克隆,深克隆有两种实现方式
实现方式一:重写clone()方法,在方法内对属性进行克隆
package cn.zzit.prototype;import java.util.Date;public class Sheep2 implements Cloneable { private String name; private Date birthday; public Sheep2(String name, Date birthday) { super(); this.name = name; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override protected Object clone() throws CloneNotSupportedException { // 深复制,复制了对象最初的值,如果对最初的值做了修改,则不会影响复制对象 Object obj = super.clone(); Sheep2 s2 = (Sheep2) obj; s2.birthday = (Date) this.birthday.clone(); return obj; }}
测试代码:
package cn.zzit.prototype;import java.util.Date;/** * 测试深复制 * @author yufu * */public class Client2 { public static void main(String[] args) throws Exception { Date date=new Date(12366521155L); Sheep2 s1=new Sheep2("多利羊",date); Sheep2 s2=(Sheep2) s1.clone(); System.out.println("s1对象:"+s1); System.out.println("s1对象的名字:"+s1.getName()); System.out.println("s1对象的生日:"+s1.getBirthday()); date.setTime(55521452236L); System.out.println("修改s1对象的生日:"+s1.getBirthday()); System.out.println("克隆的s2对象:"+s2); System.out.println("克隆的s2对象:"+s2.getName()); System.out.println("克隆的s2对象:"+s2.getBirthday()); }}
输出结果:
s1对象:cn.zzit.prototype.Sheep2@15db9742s1对象的名字:多利羊s1对象的生日:Sun May 24 11:08:41 CST 1970修改s1对象的生日:Tue Oct 05 22:37:32 CST 1971克隆的s2对象:cn.zzit.prototype.Sheep2@5c647e05克隆的s2对象:多利羊克隆的s2对象:Sun May 24 11:08:41 CST 1970
由输出结果可以看出:虽然s1对象的生日属性值已经修改但是,克隆的得到的对象s2仍然是s1修改以前的值。
实现方式二:使用序列化和反序列化,需要克隆对象实现序列化接口
package cn.zzit.prototype;import java.io.Serializable;import java.util.Date;public class Sheep3 implements Cloneable, Serializable { /** * */ private static final long serialVersionUID = 1745954590009044884L; private String name; private Date birthday; public Sheep3(String name, Date birthday) { super(); this.name = name; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override protected Object clone() throws CloneNotSupportedException { Object obj = super.clone(); return obj; }}
测试代码:
package cn.zzit.prototype;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.Date;/** * 测试深复制 使用序列化和反序列化实现 * * @author yufu * */public class Client3 { public static void main(String[] args) throws Exception { Date date = new Date(12366521155L); Sheep3 s1 = new Sheep3("多利羊", date); System.out.println("s1对象:" + s1); System.out.println("s1对象的名字:" + s1.getName()); System.out.println("s1对象的生日:" + s1.getBirthday()); // 序列化将s1对象写入流中 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(s1); byte[] b = bos.toByteArray(); oos.close(); bos.close(); date.setTime(55521452236L); System.out.println("修改s1对象的生日:" + s1.getBirthday()); // 反序列化从流中读出之前写入流中的数据 ByteArrayInputStream bis = new ByteArrayInputStream(b); ObjectInputStream ois = new ObjectInputStream(bis); Sheep3 s2 = (Sheep3) ois.readObject(); ois.close(); bis.close(); System.out.println("克隆的s2对象:" + s2); System.out.println("克隆的s2对象:" + s2.getName()); System.out.println("克隆的s2对象:" + s2.getBirthday()); }}
输出结果:
s1对象:cn.zzit.prototype.Sheep3@15db9742s1对象的名字:多利羊s1对象的生日:Sun May 24 11:08:41 CST 1970修改s1对象的生日:Tue Oct 05 22:37:32 CST 1971克隆的s2对象:cn.zzit.prototype.Sheep3@6d311334克隆的s2对象:多利羊克隆的s2对象:Sun May 24 11:08:41 CST 1970
由输出结果同样可以看到,即使s1对象发生了变化,但是由于对象实现了深复制,所以克隆得到的对象s2并未随着s1的变化而变化。
比较深克隆与浅克隆:
浅克隆相当于复制了对象地址的引用,如果引用的值发生了改变,克隆得到的对象也随之发生变化;深克隆相当于复制了最先存储在那个内存地址上的值,如果克隆发生在那个值改变之前,克隆得到的对象并不会随着原有值的改变而改变。
最后,咱们简单的说一下克隆方式的应用场景,一般情况下克隆方式会用在对象的创建比较频繁,而且创建一次对象比较耗时的情况下。
实现代码:
package cn.zzit.prototype;public class CloneSheep implements Cloneable { public CloneSheep() { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
测试代码:
package cn.zzit.prototype;public class Client4 { public static void testNew(int size) { long start = System.currentTimeMillis(); for (int i = 0; i < size; i++) { CloneSheep cs = new CloneSheep(); } long end = System.currentTimeMillis(); System.out.println("使用new创建对象耗时:" + (end - start) + "毫秒"); } public static void testClone(int size) throws Exception { long start = System.currentTimeMillis(); CloneSheep cs = new CloneSheep(); for (int i = 0; i < size; i++) { CloneSheep cs2 = (CloneSheep) cs.clone(); } long end = System.currentTimeMillis(); System.out.println("使用克隆方式创建对象耗时:" + (end - start) + "毫秒"); } public static void main(String[] args) throws Exception { testNew(1000); testClone(1000); }}
输出结果:
使用new创建对象耗时:10334毫秒使用克隆方式创建对象耗时:10毫秒
阅读全文
0 0
- java设计模式之原型设计模式
- java 设计模式之原型模式Prototype
- Java:设计模式之原型模式(Prototype)
- java设计模式之原型模式
- java设计模式之原型模式
- java设计模式之原型模式
- 【Java设计模式】之原型模式
- java设计模式笔记之原型模式
- Java设计模式之原型模式(7)
- Java--设计模式之原型模式
- JAVA设计模式之原型模式
- Java设计模式之原型模式
- JAVA设计模式之原型模式
- JAVA设计模式之原型模式
- java之设计模式---原型模式
- java设计模式之原型模式
- 《Java设计模式》之原型模式
- JAVA设计模式之原型模式
- tomcat9.0免安装配置
- 决策树(Decision Tree)
- CGI environment variables
- 剑指Offer_面试题40_数组中只出现一次的数字
- javafx自定义窗体(高级篇)
- java设计模式之原型模式
- 第二章 进程管理 2.1 进程基本概念
- 学习曲线
- Vue 通讯组件
- 智能小车27:4个Protel小技巧
- 区间动态规划及树形动态规划
- isdigit函数,isalpha函数
- sc2017新高二&高一模拟赛10 总结
- razor imu 9dof的使用,先锋机器人rosaria 理解,配置STM32-ROS通信等疑难杂症(持续更新中)