设计模式三(原型模式)

1 定义

用原型实例指定创建对象的种类,通过拷贝这些原型,创建新的对象
简单理解就是对象的克隆
2 使用clone方法实现 在java中可以使用Object对象中的clone方法来实现。
首先,如果想实现clone方法必须实现Cloneable接口,如下:
public class User implements Cloneable{ private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; }@Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }

这样看起来重写的clone方法什么都没做,为什么要实现一遍呢?因为在Object中,这个方法是protected的,意味着除了在子类的内部,以及同一个包下(Object所在的java.lang包),其他地方无法调用clone方法。关于protocted访问控制修饰符的具体作用范围,建议看这篇文章:Java 访问权限控制:你真的了解 protected 关键字吗?
注意,重写后的clone方法还是protected的,为了方便使用,可以将其提升为public,同时,返回可以改为User类型,可以看看协变返回类型,重写后如下:
public class User implements Cloneable{ private String username; private String password; public User(String username, String password) { this.username = username; this.password = password; }@Override public User clone() throws CloneNotSupportedException { return (User) super.clone(); } }

但是,这种方式只是浅拷贝,如果User中有一个引用,这个引用并不会被拷贝,比如这样:
public class User implements Cloneable{ private String username; private String password; private User friend; public User(String username, String password) { this.username = username; this.password = password; }@Override public User clone() throws CloneNotSupportedException { return (User) super.clone(); } public User getFriend() { return friend; }public void setFriend(User friend) { this.friend = friend; } }

拷贝后friend还是同一份引用。
public class Test { public static void main(String[] args) throws CloneNotSupportedException { User user = new User("leon", "123"); user.setFriend(new User("friend", "123")); User clone1 = user.clone(); System.out.println(clone1 == user); // 返回false System.out.println(user.getFriend() == clone1.getFriend()); // 返回true } }

【设计模式三(原型模式)】如果要深拷贝,需要在clone方法中处理:
@Override public User clone() throws CloneNotSupportedException { User cloneUser = (User) super.clone(); if (this.friend != null) { cloneUser.setFriend(this.friend.clone()); } return cloneUser; }

2 使用对象序列化与反序列化实现
public User deepCopy() { User cloneUser = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bai = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bai); cloneUser = (User) ois.readObject(); } catch (Exception e) { e.printStackTrace(); } return cloneUser; }

总结
  • 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能提高效率
  • 不用重新初始化对象,而是动态获得对象运行时的状态

    推荐阅读