• 设计模式之原型模式


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

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

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

  • 相关阅读:
    85--spring cloud (Ribbon-Eureka注册中心)
    85--spring cloud 入门(springcloud简介)
    84--spring cloud 入门(微服务注册中心介绍)
    83--spring cloud 入门(Eureka注册中心)
    82--JT项目20(订单模块实现/ThreadLocal本地线程变量/Quartz框架)
    81--JT项目19(商品购物车/详情/用户退出)
    80--JT项目18(Dubbo负载均衡/单点登录/注册业务)
    Ajax中post与get的区别
    Process
    Java实现CURL,与把字符串结果写到json文件
  • 原文地址:https://www.cnblogs.com/shicaiyou/p/9338174.html
Copyright © 2020-2023  润新知