欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

设计模式之原型模式

程序员文章站 2022-03-13 10:24:35
找工作时我们经常需要复印几份相同的简历。如果用编程来实现就是简单的复制粘贴,我们觉得很理所当然。 可以看出我们需要几份简历就需要实例化几次。如果写错一个字,也得改很多次。那有没有一种更简洁的方式呢?那就是原型模式了 原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 我们用原 ......

找工作时我们经常需要复印几份相同的简历。如果用编程来实现就是简单的复制粘贴,我们觉得很理所当然。

public class Resume {
    private String name;
    private String sex;
    private String age;
    private String timeArea;
    private String company;
    
    public Resume(String name){
        this.name = name;
    }
    //设置个人信息
    public void setPersonalInfo(String sex, String age){
        this.sex = sex;
        this.age = age;
    }
    //设置工作经历
    public void setWorkExperience(String timeArea, String company){
        this.timeArea = timeArea;
        this.company = company;
    }
    public void show(){
        System.out.println(name + " " + age + " " + sex);
        System.out.println("工作经历:" + timeArea + " " + company);
    }
    
}

public class Test{
    public static void main(String[] args){
        Resume resume1 = new Resume("zhangsan");
        resume1.setPersonalInfo("boy", "28");
        resume1.setWorkExperience("2016.3-2018.4", "xxxx         
                company");
        
        Resume resume2 = new Resume("wangmazi");
        resume2.setPersonalInfo("girl", "18");
        resume2.setWorkExperience("2015.3-2018.9", "xxxx 
                 company");
        
        resume1.show();
        resume2.show();
     }
}

可以看出我们需要几份简历就需要实例化几次。如果写错一个字,也得改很多次。那有没有一种更简洁的方式呢?那就是原型模式了

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

设计模式之原型模式

我们用原型模式来实现一下简历复制。

public class Resume3 implements Cloneable{
    private String name;
    private String sex;
    private String age;
    private WorkExperience we = new WorkExperience();
    
    public Resume3(String name){
        this.name = name;
    }
    //设置个人信息
    public void setPersonalInfo(String sex, String age){
        this.sex = sex;
        this.age = age;
    }
    //设置工作经历
    public void setWorkExperience(String timeArea, String company){
        we.setTimeArea(timeArea);
        we.setCompany(company);
    }
    public void show(){
        System.out.println(name + " " + age + " " + sex);
        System.out.println("工作经历:" + we.getTimeArea() + " " + we.getCompany());
    }
    public Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
    public static void main(String[] args) throws CloneNotSupportedException{
        Resume3 resume1 = new Resume3("zhangsan");
        resume1.setPersonalInfo("boy", "28");
        resume1.setWorkExperience("2016.3-2018.4", "xxxx company");
        
        //浅复制
        Resume3 resume2 = (Resume3)resume1.clone();
        resume2.setWorkExperience("2015.3-2018.9", "xxxx company");
        resume1.show();
        resume2.show();
    }
}

这样代码就清爽多了,复制一份简历也非常简单。通过new方式创建对象需要每次都执行构造函数,非常低效。所以一般在初始化的信息不发生变化的情况下,克隆是最好的办法,既隐藏了对象创建的细节,又大大提高了性能。

但这其中也有问题,clone方法是这样的,如果字段是值类型,则对改字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象,也就是说引用对象数据不会克隆过来。这就称为浅复制。从上面例子也可以看出,改变resume2的workExperience对象中的数据也会改变resume1的workExperience对象中的数据,因为他们是指向同一个引用。

那如何进行深复制呢?

public class Resume4 implements Cloneable{
    private String name;
    private String sex;
    private String age;
    private WorkExperience2 we;
    
    public Resume4(String name){
        this.name = name;
        we = new WorkExperience2();
    }
    public Resume4(WorkExperience2 workExperience) throws CloneNotSupportedException{
        this.we = (WorkExperience2) workExperience.clone();
    }
    //设置个人信息
    public void setPersonalInfo(String sex, String age){
        this.sex = sex;
        this.age = age;
    }
    //设置工作经历
    public void setWorkExperience(String timeArea, String company){
        we.setTimeArea(timeArea);
        we.setCompany(company);
    }
    public void show(){
        System.out.println(name + " " + age + " " + sex);
        System.out.println("工作经历:" + we.getTimeArea() + " " + we.getCompany());
    }
    public Object clone() throws CloneNotSupportedException{
        Resume4 resume = new Resume4(this.we);
        resume.name = this.name;
        resume.age = this.age;
        resume.sex = this.sex;
        return resume;
    }
    public static void main(String[] args) throws CloneNotSupportedException{
        Resume4 resume1 = new Resume4("zhangsan");
        resume1.setPersonalInfo("boy", "28");
        resume1.setWorkExperience("2016.3-2018.4", "xxxx company");
        
        //深复制
        Resume4 resume2 = (Resume4)resume1.clone();
        resume2.setWorkExperience("2015.4-2018.9", "xxxx company");
        resume1.show();
        resume2.show();
    }
}

这就是深复制,深复制把引用对象的变量指向复制过的对象,而不是原有的被引用的对象。我们发现如果引用中嵌套多层引用,深复制就变得很复杂,需要事先考虑清楚,小心处理。