原型模式 ?"影分身模式"

172 阅读3分钟

原型模式分为浅克隆与深克隆,克隆模式简单来说就是克隆对象的属性,不管是深度克隆也好,记住了它也不是和原来对象引用指向同一个hashCode地址。意思即使二者并不是同一个对象。浅克隆只是克隆对象的基本属性。深克隆克隆了基本属性和引用属性。大概了解了思路,我们一起来看看代码。

浅克隆

当前对象内变量无引用时,需要克隆对象状态的需求时,浅克隆完全可以胜任。无需继续new出对象赋值。

public class People implements Cloneable{

    private String name;
    private int age;
    private String home;

    public People(String name, int age, String home) {
        this.name = name;
        this.age = age;
        this.home = home;
    }

    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 getHome() {
        return home;
    }

    public void setHome(String home) {
        this.home = home;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", home='" + home + '\'' +
                '}';
    }

    public People clone() throws CloneNotSupportedException {
        return (People) super.clone();
    }
}
public class ModeTest {

    /**
     * 浅克隆: 不用重新初始化对象,动态获取对象运行时的状态
     *          可以简化对象的创建过程
     *
     * @param args
     */
    public static void main(String[] args) {
        People people = new People("原型", 1, "shanghai");
        System.out.println(people.toString());
        System.out.println("原型HaseCode: "+  people.hashCode());

        People people1 = null;
        try {
            people1 = people.clone();
            System.out.println(people1);
            System.out.println("克隆HaseCode: "+  people1.hashCode());
        } catch (CloneNotSupportedException e) {
            System.out.println(e.getMessage());
        }

        System.out.println(people == people1);

        people.setAge(100);
        System.out.println(people1);

    }
}

下面来看一下运行结果:

People{name='原型', age=1, home='shanghai'}
原型HaseCode: 356573597
People{name='原型', age=1, home='shanghai'}
克隆HaseCode: 1735600054
false
People{name='原型', age=1, home='shanghai'}

Process finished with exit code 0

可以看出来,对象的状态已经完全克隆下来了,但是引用并不是指向同一个对象。

深克隆

当一个对象内有引用时,浅克隆就显得有些无力了,那现在就需要用到深克隆,通过重写clone方法将引用对象的状态引入进来即可。

public class DeepFood implements Cloneable {

    private String name;

    @Override
    public DeepFood clone() throws CloneNotSupportedException {
        return (DeepFood) super.clone();
    }

    public DeepFood(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "DeepFood{" +
                "name='" + name + '\'' +
                '}';
    }
}
public class DeepPeople implements Serializable ,Cloneable{

    private String name;
    private int age;
    private String home;
    private DeepFood deepFood;

    public DeepPeople(String name, int age, String home) {
        this.name = name;
        this.age = age;
        this.home = home;
    }

    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 getHome() {
        return home;
    }

    public void setHome(String home) {
        this.home = home;
    }

    public DeepFood getDeepFood() {
        return deepFood;
    }

    public void setDeepFood(DeepFood deepFood) {
        this.deepFood = deepFood;
    }

    @Override
    public String toString() {
        return "DeepPeople{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", home='" + home + '\'' +
                ", deepFood=" + deepFood +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        DeepPeople deepPeople = (DeepPeople) super.clone();
        deepPeople.setDeepFood(this.deepFood.clone());
        return deepPeople;
    }
}
public class DeepModeTest {

    public static void main(String[] args) {
        // 第一种方式深克隆 通过重写cloneable的clone方法
        DeepFood deepFood = new DeepFood("food");
        DeepPeople deepPeople = new DeepPeople("深度", 2, "shanghai");
        deepPeople.setDeepFood(deepFood);

        try {
            DeepPeople deepPeople1 = (DeepPeople) deepPeople.clone();
            System.out.println(deepPeople1);
            System.out.println(deepPeople == deepPeople1);
        }catch (CloneNotSupportedException e) {
            System.out.println(e.getMessage());
        }
    }
}

来看下运行结果

DeepPeople{name='深度', age=2, home='shanghai', deepFood=DeepFood{name='food'}}
false

我们可以清楚的看到DeepPeople中通过调用food类的浅克隆方法获取到food类的状态赋值给自身的引用,完成了深克隆。

详细源码下载地址:github.com/Liyinzuo/De…

小结

克隆模式分为浅克隆,实现方法即是继承cloneable类调用父类的克隆方法完成浅克隆,浅克隆的缺点即是无法克隆对象内的引用。而深克隆弥补了浅克隆的缺点,通过重写clone方法将引用对象的状态注入进来完成深克隆。

tips:深浅克隆都只是克隆对象的状态,并不是在jvm中指向同一个对象。

spring运用

<bean id="" class="" scope="prototype"/>

也可以通过注解方式

@Scope("prototype")

以上即是克隆模式的介绍,如果有错误或者不足的地方,欢迎指正。