美文网首页
原型模式

原型模式

作者: Jackson杰 | 来源:发表于2019-01-03 14:41 被阅读0次

    一 定义

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
    原型模式也是一种创建型模式,不同的是,新对象的创建不是通过new来创建,而是在有一个原型对象的基础上通过克隆的方式,快速生成一个和原对象一样的实例。

    二 使用场景

    • 资源优化:当类的初始化需要消耗非常多的资源时,这个资源包括数据资源,硬件资源等。
    • 性能和安全要求:通过new产生一个对象需要非常繁琐的数据准备和访问权限。
    • 一个对象,多个修改者:一个对象需要提供给其它对象访问,而且各个调用者可能都要修改其值时。

    三 模式结构

    • Client:客户端用户
    • Prototype:抽象类或者接口,声明具备clone能力
    • ConcretePrototype:具体的原型类

    四 实例

    定义一个类,实现简历的功能,然后通过复制的方式,复制简历。

    public class Resume implements Cloneable {
    
        private String name;
        private String birthday;
        private String school;
    
        /**
         * 构造方法
         * @param name
         */
        public Resume(String name) {
            this.name = name;
        }
    
        public void setPersonInfo(String birthday, String school) {
            this.birthday = birthday;
            this.school = school;
        }
    
        public void display(){
            System.out.println("姓名:"+name);
            System.out.println("生日:"+birthday+" 毕业院校:"+school);
        }
    
        /**
         * 克隆该实例
         * @return
         */
       @Override
        protected Object clone(){
            Resume resume=null;
    
            try {
                resume= (Resume) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return resume;
        }
    
    }
    

    客户端测试

     Resume resume1=new Resume("Jackson");
            resume1.setPersonInfo("1990-05-23","华中科技大学");
    
            Resume resume2= (Resume) resume1.clone();
    
            System.out.println("-------------------- resume1 ----------------------");
            resume1.display();
            System.out.println("-------------------- resume2 ----------------------");
            resume2.display();
    

    浅拷贝和深拷贝

    运用原型模式,实际上只是一个浅拷贝,该拷贝并不是将原始文档上的所有字段都重新构造了一份,而是拷贝文档的字段对原始文档字段的引用。
    我们在上面代码加一个字段,设置公司的网列表。

    public class Resume implements Cloneable {
    
        private String name;
        private String birthday;
        private String school;
    
        private List<String> company=new ArrayList<>();
    
       /**
         * 添加公司
         * @param company
         */
        public void addCompany(String company){
            this.company.add(company);
        }
    
    
        public void display(){
            System.out.println("姓名:"+name);
            System.out.println("生日:"+birthday+" 毕业院校:"+school);
            for (String company:company){
                System.out.println("company:"+company);
            }
        }
    
        /**
         * 克隆该实例
         * @return
         */
        @Override
        protected Object clone(){
            Resume resume=null;
    
            try {
                resume= (Resume) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return resume;
        }
    
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getBirthday() {
            return birthday;
        }
    
        public void setBirthday(String birthday) {
            this.birthday = birthday;
        }
    
        public String getSchool() {
            return school;
        }
    
        public void setSchool(String school) {
            this.school = school;
        }
    
        public List<String> getCompany() {
            return company;
        }
    
        public void setCompany(List<String> company) {
            this.company = company;
        }
    }
    

    客户端代码如下

     Resume resume1=new Resume();
            resume1.setName("Jackson");
            resume1.setBirthday("1990-05-23");
            resume1.setSchool("华中科技大学");
            resume1.addCompany("腾讯");
            resume1.addCompany("阿里巴巴");
            resume1.addCompany("百度");
    
    
            Resume resume2= (Resume) resume1.clone();
            resume2.setName("Lucy");
            resume2.setBirthday("1992-05-17");
            resume2.setSchool("华东师范大学");
    
            resume2.addCompany("小米");
    
    
            System.out.println("-------------------- resume1 ----------------------");
            resume1.display();
            System.out.println("-------------------- resume2 ----------------------");
            resume2.display();
    

    我们在resume2里添加了小米,如果是深拷贝,resume1里应该不会有小米。
    运行代码结果如下:



    从结果可以看到,resume1里出现了小米,说明修改了拷贝,原数据也修改了,对于List<String> company,拷贝数据只是原始数据的引用。

    深拷贝
    修改clone()代码如下,对浅拷贝的ArrayList<String> company也调用clone()方法。

     /**
         * 克隆该实例
         * @return
         */
        @Override
        protected Object clone(){
            Resume resume=null;
    
            try {
                resume= (Resume) super.clone();
                // 对List<String> company对象也调用clone()
                resume.company=(ArrayList<String>)this.company.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return resume;
        }
    

    运行结果如下:



    可以看到,resume1中已经没有了小米。
    原型模式比较简单,比直接new一个对象要方便多了,特别是要在一个循环体中产生大量对象时。
    但是,一定要注意,在拷贝过程中,构造方法是不会执行的。

    相关文章

      网友评论

          本文标题:原型模式

          本文链接:https://www.haomeiwen.com/subject/qmiclqtx.html