天天看点

Java原型设计模式

原型模式

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

Java原型设计模式
public class Work implements Cloneable{
    private String address;
    private int time;

    public void setAddress(String address) {
        this.address = address;
    }

    public void setTime(int time) {
        this.time = time;
    }

    @Override
    public String toString() {
        return "Work{" +
            "address='" + address + '\'' +
            ", time=" + time +
            '}';
    }

    @Override
    protected Work clone() throws CloneNotSupportedException {
        return (Work) super.clone();
    }
}
           
public class Resume implements Cloneable{
    private String name;
    private int age;
    private String company;
    private Work work;

    public Resume(String name){
        this.name = name;
        this.work = new Work();
    }

    private Resume (Work work) throws CloneNotSupportedException {
        this.work = work.clone();
    }

    public void setAge(int age){
        this.age = age;
    }

    public void setCompany(String company){
        this.company = company;
    }

    public void setWork(String address, int time) {
        work.setAddress(address);
        work.setTime(time);
    }

    public void display(){
        System.out.println(toString());
    }

    @Override
    protected Resume clone() throws CloneNotSupportedException {
        Resume resume = new Resume(this.work);
        resume.name = this.name;
        resume.age = this.age;
        resume.company = this.company;
        return resume;
    }

    @Override
    public String toString() {
        return "Resume{" +
            "name='" + name + '\'' +
            ", age=" + age +
            ", company='" + company + '\'' +
            ", work=" + work +
            '}';
    }
}
           

浅拷贝

Java的object.clone()默认为浅拷贝,即对象的基本类型属性复制值,引用类型属性复制引用。

假如没有重写Resume对象的clone()方法

Resume resume = new Resume("周小狼");
Resume a = resume.clone();
           

两个对象的name、company、work引用会指向堆中的相同空间,当对象a对work操作会影响resume。

深拷贝

如上代码所示,重写Resume的clone方法,在方法中new一个resume对象,调用private构造器,传入当前对象的work属性,构造器再调用work的clone方法拷贝属性,此处要注意,如果work的属性中存在引用类型,还需要继续递归下去,才能实现两个resume对象的完全独立。(String类型是不可变,当修改String类型的值实际上是开辟新空间写入新值,将引用指向新空间,不会影响到其他对象)

测试

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {
        Resume resume = new Resume("周小狼");
        resume.setAge(15);
        resume.setCompany("网鱼");
        resume.setWork("同仁堂",2);

        Resume a = resume.clone();
        a.setCompany("林小媛");
        a.setWork("长运堂",1);
        resume.display();
        a.display();
    }
}
           

测试结果

Resume{name='周小狼', age=15, company='网鱼', work=Work{address='同仁堂', time=2}}
Resume{name='周小狼', age=15, company='林小媛', work=Work{address='长运堂', time=1}}
           

参考资料

《大话设计模式》

Java深拷贝和浅拷贝