设计模式-创建型-原型模式

105 阅读3分钟

简介

原型模式是创建型模式的一种,其主要是用于创建重复的对象,即将一个对象克隆成另一个一样的对象。对于一些复杂的对象,其创建效率十分高效。但该方式也有一个问题,该克隆是一个浅拷贝,新克隆出来的对象中引用的对象的地址与原对象是同一个。关于深拷贝和浅拷贝,文末会做进一步探讨。

demo示例

代码

该模式的代码较为简单,首先克隆的类需要实现cloneable接口,并重写clone方法。

import java.util.Arrays;

public class City implements Cloneable{
    private String name;
    private String location;
    private String[] districts = {"d1", "d2", "d3", "d4"};

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String[] getDistricts() {
        return districts;
    }

    public void setDistricts(String[] districts) {
        this.districts = districts;
    }

    @Override
    public String toString() {
        return "City{" +
                "name='" + name + '\'' +
                ", location='" + location + '\'' +
                ", districts=" + Arrays.toString(districts) +
                '}';
    }

    @Override
    public Object clone() {
        try {
            return super.clone();//调用父clone方法
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

客户端调用

public class Test {
    public static void main(String[] args) {
        City city1 = new City();
        city1.setLocation("west");
        city1.setName("chongqing");
        System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
    }
}

深拷贝与浅拷贝

什么是深拷贝和浅拷贝

深拷贝和浅拷贝是针对object类型的数据,对于浅拷贝,拷贝的是某个对象的指针而没有拷贝指针对应的数据,即对于object类型的数据,新对象和老对象只向的是同一块内存区域。对于深拷贝,其会将所有的object数据全部拷贝一份,此时新对象和老对象只向的是不同的内存区域。

cloneable是深拷贝还是浅拷贝

我们通过一个测试实验看一下cloneable是深拷贝还是浅拷贝,还是基于上面的City类:

public class Test {
    public static void main(String[] args) {
        City city1 = new City();
        city1.setLocation("west");
        city1.setName("chongqing");
        System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
        System.out.println("---------------");
        City city2 = (City) city1.clone();
        String[] cloneArr = city2.getDistricts();
        cloneArr[0] = "d1_new";
        city2.setName("chengdu");
        System.out.println(city2);//City{name='chengdu', location='west', districts=[d1_new, d2, d3, d4]}
        System.out.println(city1);//City{name='chongqing', location='west', districts=[d1_new, d2, d3, d4]}
    }
}

从上面的测试可以看出,对于clone出来的对象,我们将其districts数组中的第一个元素进行修改,最后原对象中对应的值也被修改了,因此我们可以得出结论,cloneable是浅拷贝。

如何实现深拷贝

要实现深拷贝,最常用的方法是对原对象进行序列化,然后再恢复。还是以City对象为例,我们先将其序列化成json,然后再恢复,我们使用google的gson进行演示。 gson的坐标为:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

测试代码如下

public class Test2 {
    public static void main(String[] args) {
        City city1 = new City();
        city1.setLocation("west");
        city1.setName("chongqing");
        System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
        System.out.println("---------------");
        Gson gson = new Gson();
        String json = gson.toJson(city1);
        City city2 = gson.fromJson(json, City.class);
        String[] cloneArr = city2.getDistricts();
        cloneArr[0] = "d1_new";
        city2.setName("chengdu");
        System.out.println(city2);//City{name='chengdu', location='west', districts=[d1_new, d2, d3, d4]}
        System.out.println(city1);//City{name='chongqing', location='west', districts=[d1, d2, d3, d4]}
    }
}

对于通过json新建出来的对象ctity2,我们修改其districts中的第一个对象为d1_new,其修改值并没有影响到city1。