zoukankan      html  css  js  c++  java
  • java设计模式--原型模式

      原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。通俗来说就是克隆一个对象,而且不用知道创建对象的细节,然后对这个对象进行自定义操作。首先,我们先看一下下面的这个例子。

    //公司类
    public
    class Company { private String level; private Long workYears; public String getLevel() { return level; } public void setLevel(String level) { this.level = level; } public Long getWorkYears() { return workYears; } public void setWorkYears(Long workYears) { this.workYears = workYears; } } //实现Cloneable接口的People类(原型实例) public class People implements Cloneable { private String name; private Long age; private String gender; //公司属性,没有实现Cloneable接口 private Company company; public String getName() { return name; } public People() { //在初始People类的同时创建company实例 this.company = new Company(); } public void setName(String name) { this.name = name; } public Long getAge() { return age; } public void setAge(Long age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Company getCompany() { return company; } public void setCompany(String level,Long workYears) { //给company的属性赋值 this.company.setLevel(level); this.company.setWorkYears(workYears); } //Clone()方法,clone people类 public Object Clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return (People) clone; } public void show() { System.out.println("name:" + name + ",age:" + age + ",gender" + gender); System.out.println("name:" + name + ",level:" + company.getLevel() + ",workYears:" + company.getWorkYears()); } } public class Test { public static void main(String[] args) {
         //原型实例对象 People people
    = new People(); people.setName("zhangsan"); people.setAge(23L); people.setGender("man"); people.setCompany("A7",3L); //克隆对象1,修改age,gender属性 People clone1 = (People)people.Clone(); clone1.setAge(25L); clone1.setGender("woman"); //克隆对象2,修改age,company属性 People clone2 = (People)people.Clone(); clone2.setAge(26L); clone2.setCompany("A8",4L); people.show(); clone1.show(); clone2.show(); } }

    得到的结果为:

    name:zhangsan,age:23,genderman
    name:zhangsan,level:A8,workYears:4

    name:zhangsan,age:25,genderwoman
    name:zhangsan,level:A8,workYears:4

    name:zhangsan,age:26,genderman
    name:zhangsan,level:A8,workYears:4

      我们可以看到值类型的字段都会拷贝一份新的出来,对他们修改也不会对被克隆对象的值进行修改,但是如果字段是引用类型,则拷贝引用,但不复制引用的对象,这样的话如果我们对引用类型的字段company进行修改就会导致显示的永远是最后一次修改的值,因为拷贝出的三个引用指向一个对象,这就是浅拷贝。

      那么如果我们想把引用类型的字段也拷贝一份出来呢,那么我们就需要把引用类型也实现Cloneable接口,并重写Clone()方法,并且把引用类型的属性再拷贝一遍,代码如下:

    public class Company implements Cloneable{
    
        private String level;
        private Long workYears;
    
        public String getLevel() {
            return level;
        }
    
        public void setLevel(String level) {
            this.level = level;
        }
    
        public Long getWorkYears() {
            return workYears;
        }
    
        public void setWorkYears(Long workYears) {
            this.workYears = workYears;
        }
    
        //Clone()方法,clone company类
        public Object Clone() {
            Object clone = null;
            try {
                clone = super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
            }
            return clone;
        }
    }
    
    //实现Cloneable接口的People类
    public class People implements Cloneable {
        private String name;
        private Long age;
        private String gender;
        private Company company;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
    
            this.name = name;
        }
    
        public People() {
            //在给People赋name的同时创建company实例
            this.company = new Company();
        }
    
        public People(Company company) {
            this.company = (Company) company.Clone();
        }
    
        public Long getAge() {
            return age;
        }
    
        public void setAge(Long age) {
            this.age = age;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public Company getCompany() {
            return company;
        }
    
        public void setCompany(String level, Long workYears) {
            //给company的属性赋值
            this.company.setLevel(level);
            this.company.setWorkYears(workYears);
        }
    
        //Clone()方法,clone people类
        public Object Clone() {
            Object object = null;
            try {
                object = super.clone();
            //把引用类型company再拷贝一遍 ((People)object).company
    = (Company) this.company.Clone(); } catch (CloneNotSupportedException exception) { throw new RuntimeException(exception); } return object; } public void show() { System.out.println("name:" + name + ",age:" + age + ",gender" + gender); System.out.println("name:" + name + ",level:" + company.getLevel() + ",workYears:" + company.getWorkYears()); } }

    结果为:

    name:zhangsan,age:23,genderman
    name:zhangsan,level:A7,workYears:3

    name:zhangsan,age:25,genderwoman
    name:zhangsan,level:A7,workYears:3

    name:zhangsan,age:26,genderman
    name:zhangsan,level:A8,workYears:4

      我们可以看到对复制出的对象中的引用对象company赋值时,并没有改变原型对象,因为引用对象的变量指向了新的克隆出的对象,这就是深拷贝。

    总结:原型模式的优点就是可以快速创建对象,比直接new一个对象再进行赋值的操作性能要好,缺点就是每个类都得实现克隆方法,当有多层引用时,需要考虑是否会造成引用死循环。

  • 相关阅读:
    - 错误笔记
    只是一个没有人知道的蒟蒻
    省选前模板复习
    数学知识小结#1
    写在NOIP2018后
    Atcoder&CodeForces杂题11.7
    Atcoder&CodeForces杂题11.6
    [NOIP11.1模拟赛]补番报告
    [JZOJ5281]钦点题解--瞎搞+链表
    [JZOJ5280]膜法师题解--思维+前缀和
  • 原文地址:https://www.cnblogs.com/yimengyizhen/p/11102435.html
Copyright © 2011-2022 走看看