九折技术 九折技术
首页
  • Go
  • MIT-6824
  • 算法与数据结构
  • 面向对象
  • 代码整洁
  • 重构
  • 设计模式
  • 学习
  • 技术
  • 人文
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub

HoldDie

长期有耐心,一切才刚刚开始!
首页
  • Go
  • MIT-6824
  • 算法与数据结构
  • 面向对象
  • 代码整洁
  • 重构
  • 设计模式
  • 学习
  • 技术
  • 人文
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub
  • 代码整洁

  • 重构

  • 设计模式

    • 创建型-单例模式
    • 创建型-工厂模式
    • 创建型-建造者模式
    • 创建型-原型模式
      • 结构型-代理模式
      • 结构型-桥接模式
      • 结构型-装饰器模式
      • 结构型-适配器模式
      • 结构型-门面模式
      • 结构型-组合模式
      • 结构型-享元模式
      • 行为型-观察者模式
      • 行为型-模板模式
      • 行为型-策略模式
      • 行为型-责任链模式
      • 行为型-状态模式
      • 行为型-迭代器模式
      • 行为型-访问者模式
      • 行为型-备忘录模式
      • 行为型-命令模式
      • 行为型-解释器模式
      • 行为型-中介模式
    • 架构
    • 设计模式
    holddie
    2020-08-30

    创建型-原型模式

    # 什么是原型模式

    • 如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式,来创建新对象,以达到节省创建时间的目的。这种基于原型来创建对象的方式就叫作原型设计模式,简称原型模式。
    • 一般用于一个对象的属性已经确定,需要产生很多相同对象的时候使用。
    • Java 中自带 clone() 方法
    • 一个类想实现深克隆功能
      • 实现标记型接口 Cloneable
      • 重写 clone() 方法

    # 为什么使用原型模式

    • 可以降低一些对象的创建成本,这个创建成本主要体现在一些属性值是经过复杂的计算得到,或者从 RPC、网络、数据库、文档系统等非常慢速的 IO 中读取。

    # 深拷贝和浅拷贝的区别

    • 浅拷贝:仅赋值对象属性这一级,如果对象的属性还有引用,那么拷贝前后两者所指的对象地址相同。

    • 深拷贝:就是完完整整拷贝一个对象,包含对象内部的对象引用。

    • 解决深拷贝的方法

      • 递归拷贝对象、对象的引用对象以及引用对象的引用对象……直到要拷贝的对象只包含基本数据类型数据,没有引用对象为止。

      • 先将对象序列化,然后再反序列化成新的对象。

      • public Object deepCopy(Object object) { 
          ByteArrayOutputStream bo = new ByteArrayOutputStream(); 
          ObjectOutputStream oo = new ObjectOutputStream(bo); 
          oo.writeObject(object); 
        
          ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray()); 
          ObjectInputStream oi = new ObjectInputStream(bi); 
          return oi.readObject();
        }
        
        1
        2
        3
        4
        5
        6
        7
        8
        9

    # 浅拷贝实现

    /**
     * 浅拷贝
     *
     * @author Thomas Yang
     * @version 1.0
     * @date 2020/8/30 4:18 PM
     */
    public class ShallowCope {
    
      @SneakyThrows
      public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = (Person) person1.clone();
        System.out.println(person2.age + " " + person2.score);
        System.out.println(person2.location);
    
        System.out.println(person1.location == person2.location);
        person1.location.street = "hz";
        System.out.println(person2.location);
      }
    }
    
    class Person implements Cloneable {
      int age = 9;
      int score = 100;
      Location location = new Location("bj", 22);
    
      @Override
      protected Object clone() throws CloneNotSupportedException {
        return super.clone();
      }
    }
    
    class Location {
      String street;
      int roomNo;
    
      public Location(String street, int roomNo) {
        this.street = street;
        this.roomNo = roomNo;
      }
    
      @Override
      public String toString() {
        return "Location{" +
          "street='" + street + '\'' +
          ", roomNo=" + roomNo +
          '}';
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

    # 深拷贝实现

    /**
     * 浅拷贝
     *
     * @author Thomas Yang
     * @version 1.0
     * @date 2020/8/30 4:18 PM
     */
    public class DeepCope {
    
      @SneakyThrows
      public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = (Person) person1.clone();
        System.out.println(person2.age + " " + person2.score);
        System.out.println(person2.location);
    
        System.out.println(person1.location == person2.location);
        person1.location.street = "hz";
        System.out.println(person1.location);
        System.out.println(person2.location);
      }
    }
    
    class Person implements Cloneable {
      int age = 9;
      int score = 100;
      Location location = new Location("bj", 22);
    
      @Override
      protected Object clone() throws CloneNotSupportedException {
        Person person = (Person) super.clone();
        person.location = (Location) location.clone();
        return person;
      }
    }
    
    class Location implements Cloneable {
      String street;
      int roomNo;
    
      public Location(String street, int roomNo) {
        this.street = street;
        this.roomNo = roomNo;
      }
    
      @Override
      public String toString() {
        return "Location{" +
          "street='" + street + '\'' +
          ", roomNo=" + roomNo +
          '}';
      }
    
      @Override
      protected Object clone() throws CloneNotSupportedException {
        return super.clone();
      }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58

    # 深、浅拷贝时,是否需要特殊处理 String 类型?

    • 不需要,虽然浅拷贝后,前后两个对象的属性同时指向一个 String 地址引用
    • 但是 String 底层实现是静态数组实现,本身是不可变的,如果其中一个对象对其属性修改,并不会修改原先 String 值,只会指向新生成的 String 地址。
    • 故 String 类型的不需要特殊处理,但是如果使用 StringBuilder 那就不同了,这个指的是同一个对象,道理同上需要深拷贝,也就是需要实现 Cloneable 接口,实现 clone 方法。
    编辑
    #原型模式
    上次更新: 2020/09/08, 15:09:00
    创建型-建造者模式
    结构型-代理模式

    ← 创建型-建造者模式 结构型-代理模式→

    最近更新
    01
    行为型-访问者模式
    11-24
    02
    行为型-备忘录模式
    11-24
    03
    行为型-命令模式
    11-24
    更多文章>
    Theme by Vdoing | Copyright © 2019-2020 HoldDie | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式