類圖
實例
public interface Prototype{
Prototype clone();
}
public class ConcretePrototypeA implements Prototype {
private int age;
private String name;
private List hobbies;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List getHobbies() {
return hobbies;
}
public void setHobbies(List hobbies) {
this.hobbies = hobbies;
}
@Override
public ConcretePrototypeA clone() {
ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
concretePrototype.setAge(this.age);
concretePrototype.setName(this.name);
concretePrototype.setHobbies(this.hobbies);
return concretePrototype;
}
}
public class ConcretePrototypeB implements Prototype {
@Override
public Prototype clone() {
return null;
}
}
public class Client {
private Prototype prototype;
public Client(Prototype prototype){
this.prototype = prototype;
}
public Prototype startClone(Prototype concretePrototype){
return (Prototype)concretePrototype.clone();
}
}
public class PrototypeTest {
public static void main(String[] args) {
// 創建一個具體的需要克隆的對象
ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
// 填充屬性,方便測試
concretePrototype.setAge(18);
concretePrototype.setName("prototype");
List hobbies = new ArrayList<String>();
concretePrototype.setHobbies(hobbies);
System.out.println(concretePrototype);
// 創建Client對象,準備開始克隆
Client client = new Client(concretePrototype);
ConcretePrototypeA concretePrototypeClone = (ConcretePrototypeA) client.startClone(concretePrototype);
System.out.println(concretePrototypeClone);
System.out.println("克隆對象中的引用類型地址值:" + concretePrototypeClone.getHobbies());
System.out.println("原對象中的引用類型地址值:" + concretePrototype.getHobbies());
System.out.println("對象地址比較:"+(concretePrototypeClone.getHobbies() == concretePrototype.getHobbies()));
}
}
深克隆
例子:
public class Monkey {
public int height;
public int weight;
public Date birthday;
}
public class JinGuBang implements Serializable {
public float h = 100;
public float d = 10;
public void big(){
this.d *= 2;
this.h *= 2;
}
public void small(){
this.d /= 2;
this.h /= 2;
}
}
public class QiTianDaSheng extends Monkey implements Cloneable,Serializable {
public JinGuBang jinGuBang;
public QiTianDaSheng(){
//只是初始化
this.birthday = new Date();
this.jinGuBang = new JinGuBang();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return this.deepClone();
}
//深克隆
public Object deepClone(){
try{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
QiTianDaSheng copy = (QiTianDaSheng)ois.readObject();
copy.birthday = new Date();
return copy;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
public QiTianDaSheng shallowClone(QiTianDaSheng target){
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
qiTianDaSheng.height = target.height;
qiTianDaSheng.weight = target.height;
qiTianDaSheng.jinGuBang = target.jinGuBang;
qiTianDaSheng.birthday = new Date();
return qiTianDaSheng;
}
//淺克隆
public QiTianDaSheng deep2(QiTianDaSheng target){
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
qiTianDaSheng.height = target.height;
qiTianDaSheng.weight = target.height;
qiTianDaSheng.jinGuBang = target.jinGuBang;
qiTianDaSheng.birthday = new Date();
return qiTianDaSheng;
}
}
public class DeepCloneTest {
public static void main(String[] args) {
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
try {
QiTianDaSheng clone = (QiTianDaSheng)qiTianDaSheng.clone();
System.out.println("深克隆:" + (qiTianDaSheng.jinGuBang == clone.jinGuBang));
} catch (Exception e) {
e.printStackTrace();
}
QiTianDaSheng q = new QiTianDaSheng();
QiTianDaSheng n = q.shallowClone(q);
System.out.println("淺克隆:" + (q.jinGuBang == n.jinGuBang));
}
}
深克隆破壞單例解決方式
要麼你我們的單例類不實現Cloneable接口;
要麼我們重寫clone()方法,在clone方法中返回單例對象即可,具體代碼如下:
@Override
protected Object clone() throws CloneNotSupportedException{
return INSTANCE;
}
Cloneable源碼分析先看我們常用的ArrayList就實現了Cloneable接口,來看代碼clone()方法的實現:`
public Object clone(){
try{
ArrayList<?>v=(ArrayList<?>)
super.clone();v.elementData=Arrays.copyOf(elementData,size);
v.modCount=0;
return v;
}catch(CloneNotSupportedExceptione){
。。。
}
個人理解
感覺和之前new出來一個對象,再set值一樣,只是,這個set的功能在對象內部。對外只暴露一個clone或者其他自定義接口。
原型克隆和new的區別
原型模式和抽象工廠模式的區別
本質
本質: 克隆生成對象。
代碼地址:
https://github.com/hufanglei/pattern-learn/tree/master/src/main/java/com/example/prototype
筆記地址 https://blog.csdn.net/baidu_21349635/article/details/106086578
個人微信公衆號:
搜索: 怒放de每一天
不定時推送相關文章,期待和大家一起成長!!
完