首页 > 代码库 > 设计模式之原型模式

设计模式之原型模式

  原型设计模式(Prototype)是创建型设计模式

  原型设计模式指通过已有的对象生成新的对象,我们无需知道原有的对象具体的创建细节,通常用于创建复杂的对象

被克隆对象必须具备以下条件:

  • 实现Cloneable接口,因为在JavaJVM中,如果要执行clone()方法时,发现该类没有实现Cloneable接口就会报CloneNotSupportedException异常
  • 重写Object的clone()方法;

原型模式优点

  • 通过clone创建对象和通过new对象相比性能要后很多,因为Object的clone是native类型的,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显;
  • 简化创建对象流程;

  所以在重复创建相似类型的对象可以考虑使用原型模式,比如在循环体内创建对象时。

注意事项

  • 原型模式创建对象不会执行被克伦对象的构造函数;
  • 深克隆和浅克隆
    • 深克隆:如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象等另行拷贝;
    • 浅克隆:Object类的clone方法只会拷贝对象中的基本的数据类型(8种基本数据类型byte,char,short,int,long,float,double,boolean),对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝;

原型模式-浅克隆

import java.util.Date;public class User implements Cloneable{    private String name;        private Date birthday;        public User(String name, Date birthday) {        this.name = name;        this.birthday = birthday;    }    @Override    public String toString() {        return "User [name=" + name + ", birthday=" + birthday + "]";    }    @Override    public Object clone() throws CloneNotSupportedException {        return super.clone();    }
  ......(省略get/set)
}

  测试类

public class Client {    public static void main(String[] args) {        try {            Date birthday = new Date(1472692739L);            User user01 = new User("parry", birthday);            System.out.println("User01" + user01.toString());                        User user02 = (User) user01.clone();            System.out.println("User02" + user02.toString());                                    birthday.setTime(1451577600l);            System.out.println("修改birthdayUser01:" + user01.toString());            System.out.println("修改birthdayUser02:" + user02.toString());        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }    }}

  测试结果:

  技术分享

  说明:从测试结果看,修改了birthday之后,user01和user02都发生了发生了变化;其实浅克隆对非基本数据类型是不会拷贝的,还是引用,用下面的图表示

  技术分享

原型模式-深克隆(在克隆的时候对属性也进行克隆)

public class User implements Cloneable{    private String name;        private Date birthday;        public User(String name, Date birthday) {        this.name = name;        this.birthday = birthday;    }    @Override    public String toString() {        return "User [name=" + name + ", birthday=" + birthday + "]";    }    @Override    public Object clone() throws CloneNotSupportedException {        User user = (User) super.clone();        user.birthday = (Date) this.birthday.clone();//属性克隆实现深克隆        return user;    }  ......(省略get/set)}

  测试结果:

  技术分享

  说明:从测试结果看,修改了birthday之后,只有user01的birthday发生了变化;其实深克隆对非基本数据类型会重新克隆一份,用面的图表示:

  技术分享

  

设计模式之原型模式