【GOF23设计模式】原型模式
来源:http://www.bjsxt.com/
一、【GOF23设计模式】_原型模式、prototype、浅复制、深复制、Cloneable接口
浅复制
1 package com.test.prototype; 2 3 import java.util.Date; 4 5 /** 6 * 浅复制 7 */ 8 public class Sheep implements Cloneable{//Cloneable为标记接口 9 private String sname; 10 private Date birthday; 11 12 @Override 13 protected Object clone() throws CloneNotSupportedException { 14 Object obj = super.clone();//直接调用object对象的clone()方法 15 return obj; 16 } 17 18 public Sheep() { 19 } 20 21 public Sheep(String sname, Date birthday) { 22 super(); 23 this.sname = sname; 24 this.birthday = birthday; 25 } 26 27 public String getSname() { 28 return sname; 29 } 30 31 public void setSname(String sname) { 32 this.sname = sname; 33 } 34 35 public Date getBirthday() { 36 return birthday; 37 } 38 39 public void setBirthday(Date birthday) { 40 this.birthday = birthday; 41 } 42 }
1 package com.test.prototype; 2 3 import java.util.Date; 4 /** 5 * 测试原型模式(浅复制) 6 */ 7 public class Client { 8 public static void main(String[] args) throws Exception { 9 Date date = new Date(3333332323L); 10 Sheep s1 = new Sheep("少利", date); 11 Sheep s2 = (Sheep) s1.clone(); 12 13 System.out.println(s1); 14 System.out.println(s1.getSname()); 15 System.out.println(s1.getBirthday()); 16 date.setTime(332324355555555L);//浅复制:s1和s2指向同一date对象的地址,一改全改 17 System.out.println(s1.getBirthday());//s1.getBirthday() == s2.getBirthday() 18 19 s2.setSname("多利"); 20 System.out.println(s2); 21 System.out.println(s2.getSname()); 22 System.out.println(s2.getBirthday()); 23 } 24 }
控制台输出:s1修改时间后,s2的也跟着改(Fri Dec 10 00:59:15 CST 12500)
com.test.prototype.Sheep@1db9742 少利 Sun Feb 08 21:55:32 CST 1970 Fri Dec 10 00:59:15 CST 12500 com.test.prototype.Sheep@647e05 多利 Fri Dec 10 00:59:15 CST 12500
深复制
1 package com.test.prototype; 2 3 import java.util.Date; 4 5 /** 6 * 深复制 7 */ 8 public class Sheep2 implements Cloneable{//Cloneable为标记接口 9 private String sname; 10 private Date birthday; 11 12 @Override 13 protected Object clone() throws CloneNotSupportedException { 14 Object obj = super.clone();//直接调用object对象的clone()方法 15 16 //添加如下代码实现深复制(Deep Clone) 17 Sheep2 s = (Sheep2) obj; 18 s.birthday = (Date) this.birthday.clone();//属性克隆! 19 20 return obj; 21 } 22 23 public Sheep2() { 24 } 25 26 public Sheep2(String sname, Date birthday) { 27 super(); 28 this.sname = sname; 29 this.birthday = birthday; 30 } 31 32 public String getSname() { 33 return sname; 34 } 35 36 public void setSname(String sname) { 37 this.sname = sname; 38 } 39 40 public Date getBirthday() { 41 return birthday; 42 } 43 44 public void setBirthday(Date birthday) { 45 this.birthday = birthday; 46 } 47 }
1 package com.test.prototype; 2 3 import java.util.Date; 4 /** 5 * 测试原型模式(深复制) 6 */ 7 public class Client2 { 8 public static void main(String[] args) throws Exception { 9 Date date = new Date(3333332323L); 10 Sheep2 s1 = new Sheep2("少利", date); 11 Sheep2 s2 = (Sheep2) s1.clone(); 12 13 System.out.println(s1); 14 System.out.println(s1.getSname()); 15 System.out.println(s1.getBirthday()); 16 date.setTime(332324355555555L);//浅复制:s1和s2指向同一date对象的地址,一改全改 17 System.out.println(s1.getBirthday());//s1.getBirthday() == s2.getBirthday() 18 19 s2.setSname("多利"); 20 System.out.println(s2); 21 System.out.println(s2.getSname()); 22 System.out.println(s2.getBirthday()); 23 } 24 }
控制台输出:s1修改时间后,s2还是最初的(Sun Feb 08 21:55:32 CST 1970)
com.test.prototype.Sheep2@1db9742 少利 Sun Feb 08 21:55:32 CST 1970 Fri Dec 10 00:59:15 CST 12500 com.test.prototype.Sheep2@647e05 多利 Sun Feb 08 21:55:32 CST 1970
二、【GOF23设计模式】_原型模式、反序列化实现深复制、效率对比、创建型模式总结
利用序列化和反序列化技术实现深复制
1 package com.test.prototype; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.ByteArrayOutputStream; 5 import java.io.ObjectInputStream; 6 import java.io.ObjectOutputStream; 7 import java.util.Date; 8 /** 9 * 原型模式(使用序列化和反序列化的方式实现深复制) 10 */ 11 public class Client3 { 12 public static void main(String[] args) throws Exception { 13 Date date = new Date(3333332323L); 14 Sheep s1 = new Sheep("少利", date); 15 16 System.out.println(s1); 17 System.out.println(s1.getSname()); 18 System.out.println(s1.getBirthday()); 19 20 // Sheep s2 = (Sheep) s1.clone(); 21 //使用序列化和反序列化实现深复制 22 //序列化 23 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 24 ObjectOutputStream oos = new ObjectOutputStream(bos); 25 oos.writeObject(s1); 26 byte[] bytes = bos.toByteArray(); 27 28 //反序列化 29 ByteArrayInputStream bis = new ByteArrayInputStream(bytes); 30 ObjectInputStream ois = new ObjectInputStream(bis); 31 32 Sheep s2 = (Sheep) ois.readObject();//深复制的对象 33 34 System.out.println("修改原型对象的属性值"); 35 date.setTime(332324355555555L); 36 System.out.println(s1.getBirthday()); 37 38 s2.setSname("多利"); 39 System.out.println(s2); 40 System.out.println(s2.getSname()); 41 System.out.println(s2.getBirthday()); 42 } 43 }
短时间大量创建对象时,原型模式和普通new方式效率测试:
1 package com.test.prototype; 2 /** 3 * 测试普通new方式创建对象和clone方式创建对象的效率差异! 4 * 如果需要短时间创建大量对象,并且new的过程比较耗时,则可以考虑使用原型模式! 5 */ 6 public class Client4 { 7 8 public static void testNew(int size){ 9 long start = System.currentTimeMillis(); 10 for (int i = 0; i < size; i++) { 11 Laptop t = new Laptop(); 12 } 13 long end = System.currentTimeMillis(); 14 System.out.println("new的方式创建耗时:" + (end - start)); 15 } 16 17 public static void testClone(int size) throws CloneNotSupportedException{ 18 long start = System.currentTimeMillis(); 19 Laptop t = new Laptop(); 20 for (int i = 0; i < size; i++) { 21 Laptop temp = (Laptop) t.clone(); 22 } 23 long end = System.currentTimeMillis(); 24 System.out.println("clone的方式创建耗时:" + (end - start)); 25 } 26 27 public static void main(String[] args) throws Exception { 28 testNew(1000); 29 testClone(1000); 30 } 31 } 32 33 class Laptop implements Cloneable{//笔记本电脑 34 public Laptop(){ 35 try{ 36 Thread.sleep(10);//模拟创建对象耗时的过程! 37 }catch(InterruptedException e){ 38 e.printStackTrace(); 39 } 40 } 41 42 @Override 43 protected Object clone() throws CloneNotSupportedException { 44 Object obj = super.clone();//直接调用object对象的clone()方法 45 return obj; 46 } 47 }
控制台输出:
new的方式创建耗时:10168
clone的方式创建耗时:10
开发中的应用场景:
原型模式很少单独出现,一般和工厂模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。
spring中bean的创建实际就是两种:单例模式和原型模式(原型模式需要和工厂模式搭配起来)。
创建型模式的总结:
posted on 2016-08-24 12:30 ErBing 阅读(...) 评论(...) 编辑 收藏