spring中的scope=“prototype”,JSON.parseObject()都是一種原型模式。
原型模式適合以下場景:
- 類初始化消耗資源較多
- new一個對象很麻煩
- 構(gòu)造函數(shù)很復(fù)雜
- 循環(huán)體中產(chǎn)生大量對象
淺克隆
標(biāo)準(zhǔn)的原型模式:
接口:
public interface Prototype {
Prototype clone();
}
需要被克隆的類:
public class ConcretePrototypeA implements Prototype {
private int age;
private String name;
private List<String> 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<String> getHobbies() {
return hobbies;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
@Override
public Prototype clone() {
ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA();
concretePrototypeA.setAge(this.age);
concretePrototypeA.setName(this.name);
concretePrototypeA.setHobbies(this.hobbies);
return concretePrototypeA;
}
}
clinet類:
public class Client {
private Prototype prototype;
public Client(Prototype prototype) {
this.prototype = prototype;
}
public Prototype startClone(Prototype prototype){
return prototype.clone();
}
}
測試代碼:
@Test
public void test1() {
ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA();
concretePrototypeA.setAge(18);
concretePrototypeA.setName("Tom");
concretePrototypeA.setHobbies(Arrays.asList("hob", "by"));
// 創(chuàng)建client準(zhǔn)備克隆
Client client = new Client(concretePrototypeA);
ConcretePrototypeA clone = (ConcretePrototypeA) client.startClone(concretePrototypeA);
System.out.println("clone = " + clone);
System.out.println(concretePrototypeA.getHobbies());
System.out.println(clone.getHobbies());
System.out.println(concretePrototypeA.getHobbies() == clone.getHobbies());
}
運行結(jié)果不盡人意,引用類型并沒有完全克隆,只復(fù)制了值類型。
深克隆
用序列化反序列化實現(xiàn):
@Data
public class Monkey implements Serializable {
private int height;
private int weight;
public Date birthday;
}
@Data
public class JinGuBang implements Serializable {
private float h = 100;
private float d = 10;
public void big() {
this.d *= 2;
this.h *= 2;
}
public void small(){
this.d /= 2;
this.h /= 2;
}
}
@Data
public class QiTianDaSheng extends Monkey implements Cloneable, Serializable {
private JinGuBang jinGuBang;
public QiTianDaSheng() {
this.birthday = new Date();
this.jinGuBang = new JinGuBang();
}
public QiTianDaSheng(JinGuBang jinGuBang) {
this.jinGuBang = 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();
return copy;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
測試:
@Test
public void test() throws CloneNotSupportedException {
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
QiTianDaSheng clone = (QiTianDaSheng) qiTianDaSheng.clone();
System.out.println("深克隆 "+(qiTianDaSheng==clone));
System.out.println("深克隆 "+(qiTianDaSheng.getJinGuBang()==clone.getJinGuBang()));
}
結(jié)果:
引用類型指向不同的對象,成功深克?。?/p>
克隆會破壞單例模式
需要放置克隆破壞單例模式,就要重寫clone方法,在clone方法里面返回單例對象就可以了。