原型設計模式
定義
指原型執行個體指定建立對象的種類,并且通過拷貝這些原型建立新的對象。
特點
不需要知道任何建立的細節,不調用構造函數
類型:建立型
使用場景
類初始化消耗較多資源
new 産生的一個對象需要非常繁瑣的過程(資料準備、通路權限等)
構造函數比較複雜
循環體中生産大量對象時
原型模式優缺點
優點:
原型模式性能比直接new一個對象性能高
簡化建立過程
缺點:
必須配備克隆方法
對克隆複雜對象或對克隆出的對象進行複雜改造時,容易引入風險
深拷貝、淺拷貝要運用得當
原型——擴充:深克隆 淺克隆
執行個體
原型模式通過clone的方式來建立另一個對象,而不是直接調用構造方法。這裡就涉及到深克隆與淺克隆的坑。
執行個體:Pig類需要實作Cloneable接口
public class Pig implements Cloneable {
private String name;
private Date birthday;
public Pig(String name, Date birthday) {
this.name = name;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Pig{" +
"name='" + name + '\'' +
", birthday=" + birthday +
'}'+super.toString();
}
}
調用
public class Test {
public static void main(String[] args) {
try {
Date birthday = new Date(0L);
Pig pig = new Pig("佩奇", birthday);
Pig pig1 = (Pig) pig.clone();
System.out.println(pig.toString());
System.out.println(pig1.toString());
pig.getBirthday().setTime(1200L);
System.out.println(pig.toString());
System.out.println(pig1.toString());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
此時的列印資訊:
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
此時可以發現在隻修改pig的birthday的時間的時候,pig1的時間也發生了變化。這樣就出現了問題,也就是我們說的bug,不難發現要修改這個bug,需要對pig類的clone方法進行修改,如下:
@Override
protected Object clone() throws CloneNotSupportedException {
Pig pig= (Pig) super.clone();
pig.birthday= (Date) pig.birthday.clone();
return pig;
}
即對pig中引用對象birthday也進行拷貝
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28
Pig{name='佩奇', birthday=Thu Jan 01 08:00:01 CST 1970}com.df.designpatterns.prototype.clone.Pig@7f31245a
Pig{name='佩奇', birthday=Thu Jan 01 08:00:00 CST 1970}com.df.designpatterns.prototype.clone.Pig@6d6f6e28