原型模式,以一個物件為原型進行復制(克隆)的設計模式,故引申出來深克隆與淺克隆知識。
舉個例子:比如我們要抄襲某位博主的部落格,部落格包括 標題,正文,文末的引流連結
我們有兩個類
public class Blog {
String title = "被抄襲的部落格標題";
String text = "被抄襲的部落格正文";
ReferenceLink referenceLink = new ReferenceLink();//文末的引流連結
public Blog() {
}
public Blog(String title, String text, ReferenceLink referenceLink) {
this.title = title;
this.text = text;
this.referenceLink = referenceLink;
}
public String getTitle() {
return title;
}
public String getText() {
return text;
}
public ReferenceLink getReferenceLink() {
return referenceLink;
}
}
@Override
public String toString() {
return "Blog{" +
"title='" + title + '\'' +
", text='" + text + '\'' +
", referenceLink=" + referenceLink.QQ + referenceLink.str +
'}';
}
public class ReferenceLink {
String QQ = "qq466009264";
String str = "來騷擾我呀";
public String getQQ() {
return QQ;
}
public String getStr() {
return str;
}
public void setQQ(String QQ) {
this.QQ = QQ;
}
public void setStr(String str) {
this.str = str;
}
}
現在開始抄襲了
Blog yblog = new Blog();//原部落格
Blog cblog = new Blog(yblog.title,yblog.text,yblog.referenceLink);//將原部落格抄襲
System.out.println("原部落格"+yblog);
System.out.println("抄襲部落格"+cblog);
System.out.println(yblog.hashCode() == cblog.hashCode());
false表示不相等,抄襲成功
思考,這種方式的弊端。
那麼怎麼解決這個問題呢?
利用object的方法,即object.clone。
public class Blog implements Cloneable{
String title = "被抄襲的部落格標題";
String text = "被抄襲的部落格正文";
ReferenceLink referenceLink = new ReferenceLink();
public Blog() {
}
public Blog(String title, String text, ReferenceLink referenceLink) {
this.title = title;
this.text = text;
this.referenceLink = referenceLink;
}
public String getTitle() {
return title;
}
public String getText() {
return text;
}
public ReferenceLink getReferenceLink() {
return referenceLink;
}
@Override
public String toString() {
return "Blog{" +
"title='" + title + '\'' +
", text='" + text + '\'' +
", referenceLink=" + referenceLink.QQ + referenceLink.str +
'}';
}
public static void main(String[] args) throws CloneNotSupportedException {
Blog yblog = new Blog();//原部落格
Blog cblog = (Blog)yblog.clone();//將原部落格抄襲
System.out.println("原部落格"+yblog);
System.out.println("抄襲部落格"+cblog);
System.out.println(yblog.hashCode() == cblog.hashCode());
}
}
結果似乎表明也抄襲成功了。
我們再次執行輸出結果
觀察可知,其實只是克隆了其基本資料型別,參照資料型別並沒有完全克隆,參照資料型別克隆的是參照地址,也就是說當副本改變參照資料型別時,原型也同步改變。
資料型別
深克隆: 克隆包括參照型別,開闢新空間,將值填進去
淺克隆: 克隆不包括參照型別,複製的是參照型別的地址
import java.io.Serializable;
public class ReferenceLink implements Cloneable, Serializable {
String QQ = "qq466009264";
String str = "來騷擾我呀";
public String getQQ() {
return QQ;
}
public String getStr() {
return str;
}
public void setQQ(String QQ) {
this.QQ = QQ;
}
public void setStr(String str) {
this.str = str;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
ublic class Blog implements Cloneable{
String title = "被抄襲的部落格標題";
String text = "被抄襲的部落格正文";
ReferenceLink referenceLink = new ReferenceLink();
public Blog() {
}
public Blog(String title, String text, ReferenceLink referenceLink) {
this.title = title;
this.text = text;
this.referenceLink = referenceLink;
}
public void setTitle(String title) {
this.title = title;
}
public void setText(String text) {
this.text = text;
}
public void setReferenceLink(ReferenceLink referenceLink) {
this.referenceLink = referenceLink;
}
public String getTitle() {
return title;
}
public String getText() {
return text;
}
public ReferenceLink getReferenceLink() {
return referenceLink;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Blog blog ;
blog = (Blog) super.clone();
blog.referenceLink = (ReferenceLink) referenceLink.clone();
return blog;
}
@Override
public String toString() {
return "Blog{" +
"title='" + title + '\'' +
", text='" + text + '\'' +
", referenceLink=" + referenceLink.QQ + referenceLink.str +
'}';
}
public static void main(String[] args) throws CloneNotSupportedException {
Blog yblog = new Blog();//原部落格
Blog cblog = (Blog)yblog.clone();//將原部落格抄襲
cblog.setTitle("升級版被抄襲的部落格標題");
cblog.setText("升級版被抄襲的部落格正文");
cblog.referenceLink.setQQ("抄襲者的qq");
cblog.referenceLink.setStr("別來煩我哦");
System.out.println("原部落格"+yblog);
System.out.println("抄襲部落格"+cblog);
System.out.println(yblog.hashCode() == cblog.hashCode());
}
}
看結果抄襲完全成功
方式一:分別對參照型別賦值克隆
方式二:序列化和反序列化