原型模式,以一个对象为原型进行复制(克隆)的设计模式,故引申出来深克隆与浅克隆知识。
原型模式解决的问题
举个例子:比如我们要抄袭某位博主的博客,博客包括 标题,正文,文末的引流链接
我们有两个类
原型 - Blog类
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。
- 实现Cloneable
- 调用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());
}
}
结果似乎表明也抄袭成功了。
当抄袭者怕被发现将原博客升级
我们再次运行输出结果
观察可知,其实只是克隆了其基本数据类型,引用数据类型并没有完全克隆,引用数据类型克隆的是引用地址,也就是说当副本改变引用数据类型时,原型也同步改变。
数据类型
深克隆与浅克隆
深克隆: 克隆包括引用类型,开辟新空间,将值填进去
浅克隆: 克隆不包括引用类型,复制的是引用类型的地址
深克隆
ReferenceLink 类
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();
}
}
Blog 类
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());
}
}
看结果抄袭完全成功
方式一:分别对引用类型赋值克隆
方式二:序列化和反序列化