zoukankan      html  css  js  c++  java
  • 【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的创建实际就是两种:单例模式和原型模式(原型模式需要和工厂模式搭配起来)。

    创建型模式的总结: 
    创建型模式的总结

  • 相关阅读:
    LeetCode 42. Trapping Rain Water
    LeetCode 209. Minimum Size Subarray Sum
    LeetCode 50. Pow(x, n)
    LeetCode 80. Remove Duplicates from Sorted Array II
    Window10 激活
    Premiere 关键帧缩放
    AE 「酷酷的藤」特效字幕制作方法
    51Talk第一天 培训系列1
    Premiere 视频转场
    Premiere 暴徒生活Thug Life
  • 原文地址:https://www.cnblogs.com/erbing/p/5802444.html
Copyright © 2011-2022 走看看