设计模式之原型模式

  原型设计模式(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发生了变化;其实深克隆对非基本数据类型会重新克隆一份,用面的图表示:

  

  

posted @ 2016-09-01 10:18  星星满天  阅读(196)  评论(0编辑  收藏  举报