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

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

  • 相关阅读:
    jQuery中的一些操作
    laravel使用消息队列
    Laravel的开发环境Homestead的搭建与配置
    python爬虫学习
    配置文件
    sql根据时间差查询数据
    Oracle根据连接字符串获取库下的表列表、获取表结构
    Sql根据连接字符串获取库下的表列表、获取表结构
    判断网络连接
    线程锁,解决多线程并发问题
  • 原文地址:https://www.cnblogs.com/erbing/p/5802444.html
Copyright © 2011-2022 走看看