什么是原型模式
听说过克隆吧,通俗点说,就是复制,把一个已经存在的对象当作原型,克隆出一个跟它相同的对象,这就是原型模式。
原型对象通常都是经历过初始化操作已经含有一些数据的对象,复制它就是为了省去重新初始化的过程,从而快速得到一个有目标数据的对象。
在面向对象编程领域,克隆又可以细分为两种模式:
- 浅克隆:只克隆原型对象自身,原型对象内部持有的其它对象不可隆,但是会保留对象引用。
- 深克隆:不仅克隆原型对象自身,还克隆原型对象内部持有的其它对象。
使用时,选择浅克隆还是深克隆,要根据业务场景来判断,千万不能乱用!
原型模式的实现
浅克隆
在Java
中,顶层对象类java.lang.Object
提供有一个clone()
方法,就是浅克隆的实现:
/**
* 必须实现接口:java.lang.Cloneable
*/
public class Prototype implements Cloneable {
public int number = 10;
public List<String> list = new ArrayList<>();
/**
* 重写父类clone()方法,调用super.clone()完成浅克隆
*
* @return
*/
@Override
public Prototype clone() {
try {
Prototype clone = (Prototype) super.clone();
// TODO 克隆对象以后,可以做一些其它的操作
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
自己动手实现浅克隆:
/**
* 自己动手,不需要实现接口:java.lang.Cloneable
*/
public class Prototype {
public int number = 10;
public List<String> list = new ArrayList<>();
/**
* 因为没有使用父类clone()方法,所以自定义一个其它的方法名,不使用clone
*
* @return
*/
public Prototype cloneObject() {
Prototype clone = new Prototype();
clone.number = this.number;
clone.list = this.list;
return clone;
}
}
上述两种方法都能实现浅克隆操作,克隆对象和原型对象持有的list
属性对象都是同一个。
深克隆
Java
默认没有提供深克隆的操作接口,可以在浅克隆clone()
的基础上加以变通,达到深克隆的效果:
/**
* 必须实现接口:java.lang.Cloneable
*/
public class Prototype implements Cloneable {
public int number = 10;
public List<String> list = new ArrayList<>();
/**
* 重写父类clone()方法,调用super.clone()完成浅克隆
*
* @return
*/
@Override
public Prototype clone() {
try {
Prototype clone = (Prototype) super.clone();
clone.list = new ArrayList<>(); // 主动创建一个新的list对象,实现深克隆
return clone;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
自己动手实现深克隆:
/**
* 自己动手,不需要实现接口:java.lang.Cloneable
*/
public class Prototype {
public int number = 10;
public List<String> list = new ArrayList<>();
/**
* 因为没有使用父类clone()方法,所以自定义一个其它的方法名,不使用clone
*
* @return
*/
public Prototype cloneObject() {
Prototype clone = new Prototype();
clone.number = this.number;
clone.list = new ArrayList<>(); // 区别就在这里,深克隆要把原型内部持有对象全都重新创建一遍
return clone;
}
}
上述两种方法都能实现深克隆操作,克隆对象和原型对象持有的list
属性对象不是同一个。
总结
原型模式是一个很简单的设计模式,清楚理解浅克隆和深克隆的区别很重要。
很多开源工具包里都提供有复制对象的工具类,先搞清楚它们是浅克隆复制还是深克隆复制,然后再根据实际业务场景选择使用即可。