重学设计模式之原型模式

239 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第八天,点击查看活动详情 

重学设计模式之原型模式

前言

原型(prototype)的理解需要和复制/克隆联系

原型的意思就是按照对象A,复制/拷贝一份,形成一个单独独立的新的对象B,我们对对象B进行操作,而原来被复制/拷贝的对象A就称为对象B的原型

原型模式的使用场景就是当一个对象的创建比较复杂的时候,我们耗费了一些资源好不容易创建出了一个对象A,

如果此时我们需要再创建一个对象B,那么我们不需要再去经过前面繁琐的步骤创建对象B,而是直接复制粘贴对象A,

得到一个完整对立的对象B

原型模式是一种创建型设计模式,允许一个对象再创建另外一个可定制的对象,无需知道如何创建的细节

工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它

                

原型模式的优缺点

  • 优点

    1. 性能高,简单 ;

    2. 性能高 : 使用原型模式复用的方式创建实例对象,比使用构造函数重新创建对象性能要高; ( 针对类实例对象开销大的情况 )

    3. 流程简单 : 原型模式可以简化创建的过程,可以直接修改现有的对象实例的值 ,达到复用的目的 ; ( 针对构造函数繁琐的情况 )

  • 缺点

    1. 实现复杂 

    2. 覆盖clone方法( 必须 ):必须重写对象的 clone 方法,Java 中提供了cloneable标识该对象可以被拷贝, 但是必须覆盖 Object 的 clone 方法才能被拷贝 ;

 

实例:

原型模式的克隆实现方式就是原来我们学习的对象的克隆,即实现接口Cloneable(可克隆的)并调用方法clone()

//测试类:

public class Cow implements Cloneable {
     private String name;
     private int age;
     private String color;
     private String address = "水牛";
     public Sheep friend; //是对象, 克隆是会如何处理
     public Cow(String name, int age, String color) {
         super();
         this.name = name;
         this.age = age;
         this.color = color;
     }
     public String getName() {
         return name;
     }
     public void setName(String name) {
         this.name = name;
     }
     public int getAge() {
         return age;
     }
     public void setAge(int age) {
         this.age = age;
     }
     public String getColor() {
         return color;
     }
     public void setColor(String color) {
         this.color = color;
     }
 

     //克隆该实例,使用默认的clone方法来完成
     @Override
     protected Object clone()  {
 
         Cow cow = null;
         try {
             Cow = (Cow)super.clone();
         } catch (Exception e) {
             // TODO: handle exception
             System.out.println(e.getMessage());
         }
         // TODO Auto-generated method stub
         return cow;
     }
}
public static void main(String[] args) {
         System.out.println("原型模式完成对象的创建");
        
         Cow cow = new Cow("tom", 1, "白色");
 
         cow.friend = new Cow("jack", 2, "黑色");
 
         Cow cow2 = (Cow)cow.clone(); //克隆
         Cow cow3= (Cow)cow.clone(); //克隆
         Cow cow4= (Cow)cow.clone(); //克隆
         Cow cow5= (Cow)cow.clone(); //克隆
 
         sheep.setAge(12);
 
         System.out.println("cow2 =" + cow2 + "cow2.friend=" + cow2.friend.hashCode());
         System.out.println("cow3 =" + cow3 + "cow3.friend=" + cow3.friend.hashCode());
         System.out.println("cow4 =" + cow4 + "cow4.friend=" + cow4.friend.hashCode());
        
     }

测试结果:基本的数据类型和字符串传过来了,但是对象没有,说明这是一个浅拷贝

浅拷贝的简介:

对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。

对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。

因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值

前面我们克隆羊就是浅拷贝

浅拷贝是使用默认的 clone()方法来实现 cow = (Cow) super.clone();

深拷贝基本介绍

复制对象的所有基本数据类型的成员变量值为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。 也就是说,对象进行深拷贝要对整个对象(包括对象的引用类型)进行拷贝

深拷贝实现方式 1:重写 clone 方法来实现深拷贝

深拷贝实现方式 2:通过对象序列化实现深拷贝(推荐)

深拷贝的例子小伙伴们自己实现哦