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;
}
总结
- 创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能提高效率
- 不用重新初始化对象,而是动态获得对象运行时的状态
推荐阅读
- 面试|我经历的IT公司面试及离职感受(转)
- java|设计模式——创建型——工厂方法(Factory Method)
- 设计模式|设计模式_创建型模式——工厂方法
- 设计模式|设计模式——创建型软件设计模式——工厂方法模式
- 设计模式之装饰器模式
- 设计模式之设计原则
- 设计模式六大原则(5)(迪米特法则 最少知道)
- 观察者模式实现之EventBus(Google)
- Java高级面试|常见设计模式——装饰模式
- java设计模式——单例模式