zoukankan      html  css  js  c++  java
  • GOF23设计模式之原型模式(prototype)

    一、原型模式概述

      1.通过new产生一个对象需要非常繁琐的数据准备和访问权限,则可以使用原型模式。

      2.就是java中的克隆技术,以某个对象为原型,复制出新的对象,显然,新的对象具备原型对象的特点。

      3.优势:效率高(直接克隆,避免了重新执行构造函数的过程)。

      4.克隆类似于new,但是不同于new。
        new创建出来的对象属性采用默认值,克隆出来的对象属性值完全和原型对象相同,并且克隆出的新对象不会影响原型对象,然后,再修改克隆对象的值。

      是否使用原型模式比较:

        1.如果需要创建大量不费时的对象,new的对象和clone的对象效率相当

        2.如果需要创建大量耗时的对象,建议使用原型模式

    二、原型模式三种实现方式

      1.浅复制:类中实现 Cloneable接口,重写clone方法

      2.深复制:类中实现 Cloneable接口,重写clone方法时将对象一起克隆

      3.深复制:类中实现 Serializable接口,利用反序列化实现深克隆

      浅复制,深复制知识请点击此处

    三、使用浅复制实现原型模式

      1.使用原型模式克隆多利羊

     1 /**
     2  * 原型模式(浅克隆)
     3  * @author CL
     4  *
     5  */
     6 public class Sheep implements Cloneable {
     7     private String name;
     8     
     9     public Object clone() throws CloneNotSupportedException {
    10         return super.clone();
    11     }
    12 
    13     public Sheep() {
    14     }
    15 
    16     public Sheep(String name) {
    17         this.name = name;
    18     }
    19 
    20     public String getName() {
    21         return name;
    22     }
    23 
    24     public void setName(String name) {
    25         this.name = name;
    26     }
    27     
    28 }

      2.测试

     1 public class TestSheep {
     2     
     3     public static void main(String[] args) throws Exception {
     4         Sheep s1 = new Sheep("多利");
     5         Sheep s2 = (Sheep) s1.clone();    //克隆对象
     6         
     7         System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName());
     8         System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName());
     9         
    10         s2.setName("少利");    //对克隆对象修改,不影响原对象的属性值
    11         
    12         System.out.println("
    --------修改克隆对象的属性值后---------
    ");
    13         
    14 
    15         System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName());
    16         System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName());
    17     }
    18 
    19 }

      控制台输出:

    366712642(原型对象)-->多利
    1829164700(克隆对象)-->多利
    
    --------修改克隆对象的属性值后---------
    
    366712642(原型对象)-->多利
    1829164700(克隆对象)-->少利

    四、使用深复制实现原型模式(1)

      1.使用原型模式克隆多利羊

     1 import java.util.Date;
     2 
     3 /**
     4  * 原型模式(深克隆)
     5  * @author CL
     6  *
     7  */
     8 public class Sheep implements Cloneable {
     9     private String name;
    10     
    11     private Birthday birthday;
    12     
    13     public Object clone() throws CloneNotSupportedException {
    14         Sheep s = (Sheep) super.clone();    //克隆对象
    15         s.birthday = (Birthday) this.birthday.clone();
    16         return s;
    17     }
    18 
    19     public Sheep() {
    20     }
    21 
    22     public Sheep(String name, Birthday birthday) {
    23         this.name = name;
    24         this.birthday = birthday;
    25     }
    26 
    27     public String getName() {
    28         return name;
    29     }
    30 
    31     public void setName(String name) {
    32         this.name = name;
    33     }
    34 
    35     public Birthday getBirthday() {
    36         return birthday;
    37     }
    38 
    39     public void setBirthday(Birthday birthday) {
    40         this.birthday = birthday;
    41     }
    42     
    43     
    44 }
    45 
    46 class Birthday implements Cloneable {
    47     private Date birthday;
    48     
    49     protected Object clone() throws CloneNotSupportedException {
    50         return super.clone();
    51     }
    52 
    53     public Birthday() {
    54     }
    55 
    56     public Birthday(Date birthday) {
    57         this.birthday = birthday;
    58     }
    59 
    60     public Date getBirthday() {
    61         return birthday;
    62     }
    63 
    64     public void setBirthday(Date birthday) {
    65         this.birthday = birthday;
    66     }
    67 }

      2.测试

     1 import java.util.Date;
     2 
     3 /**
     4  * 测试原型模式(深克隆)
     5  * @author CL
     6  *
     7  */
     8 public class TestSheep {
     9     
    10     public static void main(String[] args) throws Exception {
    11         Birthday date = new Birthday(new Date(5456464L));
    12         Sheep s1 = new Sheep("多利", date);
    13         Sheep s2 = (Sheep) s1.clone();    //克隆对象
    14         
    15         System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
    16         System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday());
    17         
    18         date.setBirthday(new Date());    //对原对象修改,克隆对象的属性值不改变
    19         
    20         System.out.println("
    --------修改克隆对象的属性值后---------
    ");
    21 
    22         System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
    23         System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday());
    24     }
    25 
    26 }

      控制台输出:

    366712642(原型对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
    1550089733(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
    366712642(原型对象)-->多利-->Fri Dec 29 17:03:26 CST 2017
    1550089733(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970

    五、使用深复制实现原型模式(2)

      1.使用原型模式克隆多利羊

     1 import java.io.Serializable;
     2 import java.util.Date;
     3 
     4 /**
     5  * 原型模式(利用反序列化实现深克隆)
     6  * @author CL
     7  *
     8  */
     9 public class Sheep implements Serializable {
    10     private String name;
    11     
    12     private Birthday birthday;
    13     
    14     public Sheep() {
    15     }
    16 
    17     public Sheep(String name, Birthday birthday) {
    18         this.name = name;
    19         this.birthday = birthday;
    20     }
    21 
    22     public String getName() {
    23         return name;
    24     }
    25 
    26     public void setName(String name) {
    27         this.name = name;
    28     }
    29 
    30     public Birthday getBirthday() {
    31         return birthday;
    32     }
    33 
    34     public void setBirthday(Birthday birthday) {
    35         this.birthday = birthday;
    36     }
    37     
    38 }
    39 
    40 class Birthday implements Serializable {
    41     private Date birthday;
    42 
    43     public Birthday() {
    44     }
    45 
    46     public Birthday(Date birthday) {
    47         this.birthday = birthday;
    48     }
    49 
    50     public Date getBirthday() {
    51         return birthday;
    52     }
    53 
    54     public void setBirthday(Date birthday) {
    55         this.birthday = birthday;
    56     }
    57 }

      2.测试

     1 import java.io.ByteArrayInputStream;
     2 import java.io.ByteArrayOutputStream;
     3 import java.io.ObjectInputStream;
     4 import java.io.ObjectOutputStream;
     5 import java.util.Date;
     6 
     7 /**
     8  * 测试原型模式(利用反序列化实现深克隆)
     9  * @author CL
    10  *
    11  */
    12 public class TestSheep {
    13     
    14     public static void main(String[] args) throws Exception {
    15         Birthday date = new Birthday(new Date(5456464L));
    16         Sheep s1 = new Sheep("多利", date);
    17         
    18         //利用反序列化实现深克隆
    19         //1. 序列化
    20         ByteArrayOutputStream bos = new ByteArrayOutputStream();
    21         ObjectOutputStream oos = new ObjectOutputStream(bos);
    22         oos.writeObject(s1);
    23         byte[] bytes = bos.toByteArray();
    24         
    25         //2. 反序列化
    26         ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
    27         ObjectInputStream ois = new ObjectInputStream(bis);
    28         Sheep s2 = (Sheep) ois.readObject();
    29         
    30         System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
    31         System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday());
    32         
    33         date.setBirthday(new Date());    //对原对象修改,克隆对象的属性值不改变
    34         
    35         System.out.println("
    --------------------修改克隆对象的属性值后---------------------
    ");
    36 
    37         System.out.println(s1.hashCode()+"(原型对象)-->"+s1.getName()+"-->"+s1.getBirthday().getBirthday());
    38         System.out.println(s2.hashCode()+"(克隆对象)-->"+s2.getName()+"-->"+s2.getBirthday().getBirthday());
    39     }
    40 
    41 }

      控制台输出:

    1442407170(原型对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
    1173230247(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970
    
    --------------------修改克隆对象的属性值后---------------------
    
    1442407170(原型对象)-->多利-->Fri Dec 29 17:11:21 CST 2017
    1173230247(克隆对象)-->多利-->Thu Jan 01 09:30:56 CST 1970

    六、原型模式常见应用场景

      1.原型模式很少单独出现,一般是和工厂方法模式一起出现。通过clone的方法创建一个对象,然后由工厂方法提供给调用者;

      2.Spring中的bean的创建其实就是两种:单例模式和原型模式(+工厂模式);

      3.………………

    //对原型对象的修改

  • 相关阅读:
    数据库访问性能优化--应用开发
    苹果终端wifi图标点亮慢和portal弹窗机制分析以及处理办法和建议
    蓝牙固件升级(OTA升级)原理设计
    C语言:内存字节对齐详解
    linux du与ls查看文件大小时的区别
    80211 组播速率及组播转单播
    视频帧、码流计算
    IEEE802.11数据帧在Linux上的抓取 80211格式转8023帧格式
    wifidog源码分析
    无线路由:关于WDS,Repeater等模式的说明
  • 原文地址:https://www.cnblogs.com/cao-lei/p/8145487.html
Copyright © 2011-2022 走看看