深度揭秘原型(深浅克隆)模式!
来源:互联网 发布:淘宝企业店铺装修教程 编辑:程序博客网 时间:2024/05/17 07:34
原型模式:
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
深克隆和浅克隆:
1、对于浅克隆
public class People implements Cloneable { String name; int age; Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public People(String name, int age, Date date) { super(); this.name = name; this.age = age; this.date = date; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "People [name=" + name + ", age=" + age + ", date=" + date + "]"; } public People() { super(); } public People(String name, int age) { super(); this.name = name; this.age = age; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }}
测试类:
public class Client { public static void main(String[] args) throws Exception { Date date = new Date(2364262352L); System.out.println(date); People p1 = new People("张三", 18,date); date.setTime(62786892498243L); System.out.println(date); People p2 = (People) p1.clone(); System.out.println(p1); System.out.println(p2); System.out.println(p1.hashCode() +"-----"+p2.hashCode()); /* * 打印结果: * * People [name=张三, age=18, date=Sat Aug 22 11:28:18 GMT+08:00 3959] * People [name=张三, age=18, date=Sat Aug 22 11:28:18 GMT+08:00 3959] *发现:克隆之后在修改时间依然还是没有变化。 * */ }}
对于浅克隆,如图所示:
深克隆:
这里有两种方式:
1、通过重写clone方法,来实现深克隆。
/** * 深度克隆 * */public class People2 implements Cloneable { String name; int age; Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public People2(String name, int age, Date date) { super(); this.name = name; this.age = age; this.date = date; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "People [name=" + name + ", age=" + age + ", date=" + date + "]"; } public People2() { super(); } public People2(String name, int age) { super(); this.name = name; this.age = age; } @Override protected People2 clone() throws CloneNotSupportedException { //在克隆对象的同时把对象的属性也给克隆了 Object obj = super.clone(); People2 p = (People2) obj; Date d = (Date) p.date.clone(); p.setDate(d); return p; }}
测试代码:
public class Client2 { public static void main(String[] args) throws CloneNotSupportedException { Date date = new Date(2678264781672L); People2 p = new People2("张三",12,date); People2 p1 = p.clone(); date.setTime(897892798732L); System.out.println(p); System.out.println(p1); /* * 打印结果: * People [name=张三, age=12, date=Mon Jun 15 14:39:58 GMT+08:00 1998] * People [name=张三, age=12, date=Sat Nov 14 18:26:21 GMT+08:00 2054] * 可以观察到深度克隆之后,在修改属性此时就会发生变化 * */ }}
第二种方式,通过序列化和反序列化来实现:
public class People3 implements Serializable { private static final long serialVersionUID = 1L; String name; Date date; @Override public String toString() { return "People3 [name=" + name + ", date=" + date + "]"; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public People3(String name, Date date) { super(); this.name = name; this.date = date; } public People3() { super(); // TODO Auto-generated constructor stub } //内容写到数组里边然后在读取 , 通过此种方式来深度复制对象 public People3 clone(People3 p){ //定义这个数组用于接收对象信息 byte[] by=null; //初始化字节数组输出流 ByteArrayOutputStream baos = null; //初始化对象输出流 ObjectOutputStream oos = null; try { baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); //将对象写入到硬盘中 oos.writeObject(p); by = baos.toByteArray(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { if (oos != null) { oos.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //获取字节数组输入流 ByteArrayInputStream bais = null; //获得对象输入六 ObjectInputStream ois = null; try { //读取by数组 bais = new ByteArrayInputStream(by); ois = new ObjectInputStream(bais); //通过反序列化读取到对象 People3 p1= (People3) ois.readObject(); //System.out.println(p); return p1; } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ try { bais.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } try { if (ois != null) { ois.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; }}
测试代码:
public class Client3 { public static void main(String[] args) { Date d = new Date(35483782375L); System.out.println(d); People3 p = new People3("张三",d); People3 p1 = p.clone(p); d.setTime(78946582782L); System.out.println("p的时间"+"---"+d); System.out.println("p"+"---"+p); System.out.println("p1"+"---"+p1); /* * 打印结果: * Tue Feb 16 00:36:22 GMT+08:00 1971 * p的时间---Mon Jul 03 01:36:22 GMT+08:00 1972 * p---People3 [name=张三, date=Mon Jul 03 01:36:22 GMT+08:00 1972] * p1---People3 [name=张三, date=Tue Feb 16 00:36:22 GMT+08:00 1971] * * 如上一种深克隆一样 * */ }}
那么,原型模式到底在什么时候用?
假设一个系统的产品类是动态加载的,而且产品类具有一定的等级结构。这个时候如果采取工厂模式的话,工厂类就不得不具有一个相应的等级结构。而产品品类的等级结构一旦变化,工厂类的等级结构就不得不有以恶相应的变化。这对于产品结构可能会有经常变化的系统来说,采用工厂模式就有不方便之处。
此时若采用原型模式,给每一个产品类配备一个克隆方法(大多时候只需个产品类等级结构配备一个根类配备一个克隆方法),便可免去工厂模式所带来的据哟有固定等级结构的工厂类。
还有一点,假设通过普通方法创建对象很耗时时,也可采用原型模式,例如:
/** * 测试普通new方式创建对象和clone方式创建对象的效率差异! * 如果需要短时间创建大量对象,并且new的过程比较耗时。则可以考虑使用原型模式! * * */public class Client4 { public static void testNew(int size){ long start = System.currentTimeMillis(); for(int i=0;i<size;i++){ Laptop t = new Laptop(); } long end = System.currentTimeMillis(); System.out.println("new的方式创建耗时:"+(end-start)); } public static void testClone(int size) throws CloneNotSupportedException{ long start = System.currentTimeMillis(); Laptop t = new Laptop(); for(int i=0;i<size;i++){ Laptop temp = (Laptop) t.clone(); } long end = System.currentTimeMillis(); System.out.println("clone的方式创建耗时:"+(end-start)); } public static void main(String[] args) throws Exception { testNew(1000); testClone(1000); /** * 测试结果: * new的方式创建耗时:10288 * clone的方式创建耗时:10 * * * */ }}class Laptop implements Cloneable { //笔记本电脑 public Laptop() { try { Thread.sleep(10); //模拟创建对象耗时的过程! } catch (InterruptedException e) { e.printStackTrace(); } } @Override protected Object clone() throws CloneNotSupportedException { Object obj = super.clone(); //直接调用object对象的clone()方法! return obj; }}
阅读全文
0 0
- 深度揭秘原型(深浅克隆)模式!
- 七、原型模式(深浅克隆)
- 深度克隆,原型模式
- 原型模式(重新思考深浅拷贝)
- 原型模式深浅复制
- 深入浅出设计模式 ------ Prototype(原型模式)之深度克隆
- 原型模式(克隆模式,拷贝模式)
- 原型模式中的深浅复制
- 原型模式之深浅复制
- 设计模式之原型模式(深克隆,浅克隆)
- 对象的克隆--原型模式(Prototype)
- 克隆(原型)模式
- 原型克隆模式
- 原型模式的浅度克隆和深度克隆的实现
- 深浅克隆
- 深浅克隆
- 对象的克隆——原型模式(三):浅克隆,深克隆
- 【怎样写代码】对象克隆 -- 原型模式(四):浅克隆与深克隆
- BZOJ 3991 寻宝游戏 (dfs序 RMQ set维护动态链的并集)
- uvalive 2966 求一个二分图 所有的完美匹配
- 多分支语句中的跳楼现象
- TCL学习笔记之 列表命令
- JAVA jvm和 Android dvm的区别
- 深度揭秘原型(深浅克隆)模式!
- 018 连续函数的运算及初等函数的连续性;第一类间断点、第二类间断点
- HNU OJ题库 1007H生理周期
- POJ 1961 Period
- 洛谷P1456 (HDU 1512)Monkey King
- E
- zynq学习笔记二:编译U-Boot(zybo)
- [BZOJ]1093: [ZJOI2007]最大半连通子图 Tarjan缩点+拓扑图DP
- 第四周项目二C/C++建设“单链表”算法库