• 设计模式之原型模式


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

    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();
        }
    }

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

  • 相关阅读:
    每天干攻防,都不会写驱动了
    SSD 坏了
    据说英雄联盟要出新皮肤了
    随便写点什么,证明我还活着,VS2010出现的问题
    ida 符号路径设置
    搭建一个自己的SVN服务器
    nginx+keepalived互为主主高可用配置
    nginx+keepalived主从高可用配置
    Lnamp的高级网站架构+动静分离+反向代理
    Nginx+PHP(FastCGI)高性能服务器加载redis+memcache模块
  • 原文地址:https://www.cnblogs.com/shicaiyou/p/9338174.html
Copyright © 2020-2023  润新知