一生猿,一世猿。 —— 猿医生·yys
目录
一、前言
二、简介
三、原型模式 - 浅克隆
四、原型模式 - 深克隆
一、前言
上篇 设计模式之工厂模式【选用修仙小说功法阐述】得到 CSDN官方大大以及各位猿友的推崇,小主很是倍感荣幸。
今天呢 (2020.05.22),利用【齐天大圣拔毫毛】【鸣人多重影分身】两个案例来阐述下 设计模式之原型模式。
在此,记录一下,分享给大家。
二、简介
姓名:原型模式
英文名:Prototype Pattern
个人介绍:原型模式(prototype pattern)是指用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式属于创建型的设计模式。
原型模式分为 浅克隆、深克隆。
特长爱好:1.类初始化消耗资源太多;
2.new 对象需要非常繁琐的过程 (数据准备、访问权限);
3.构造函数复杂;
4.循环中需要生成大量对象;
相信大家读到这里... ...用一首最近流行的网红洗脑神曲,“小朋友你是否有很多问号???”
不过...大家不要慌.... 按照小主的个人习惯,是时候上案例了,记得千万不要走神,车要开了。。
三、原型模式 - 浅克隆
“猴哥,猴哥”,
“你真了不得”,
“五行大山压不住你”,
“蹦出个孙行者”,
... ...
“拔一根毫毛”,
“吹出猴万个”,
... ...
一首儿时曲,忆起童年往事 ~ 越长大越孤单 ~
岁月的洪流,卷走了青春,卷走了年华,剩下的只是一个被岁月刻下深深印痕的伤痕累累的躯壳,和一颗沧桑的心。
咳 咳 ~ 一不小心,来了波醉酒驾驶,哈哈 ~
言归正传 ,大家都知道齐天大圣,手持金箍棒,拥有七十二变,拔一根毫毛,可以吹出千万个猴子猴孙。
接下来 小主将采用 【齐天大圣拔毫毛】的案例来阐述原型模式之 浅克隆方式:
首先,定义一个猴子的 Monkey 类:
@Getter
@Setter
// @Data (不使用 @Data,会重写toString()方法)
public class Monkey {
private int height;
private int width;
}
接下来,定义金箍棒 JingGuBang 类:
@Getter
@Setter
public class JinGuBang {
private float h = 99;
private float w = 9;
public void big() {
this.h *= 10;
this.w *= 10;
}
public void small() {
this.h /= 2;
this.w /= 2;
}
}
接下来,定义齐天大圣 QiTiDaSheng 类 - < 原型对象 >:
@Getter
@Setter
public class QiTianDaSheng extends Monkey implements Cloneable {
private JinGuBang jinGuBang;
public QiTianDaSheng1(JinGuBang jinGuBang) {
this.jinGuBang = jinGuBang;
}
// 重写克隆方法
@Override
protected Object clone() {
try {
Object clone = super.clone();
return clone;
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone();
}
// 浅克隆实现方式:
// 1.需实现 Cloneable接口
// 2.重写克隆方法
}
原型模式 - 浅克隆 测试类及测试结果:
public class CloneTest {
public static void main(String[] args) {
try {
// 创建原型对象
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng(new JinGuBang()); // 传入金箍棒
qiTianDaSheng.setWidth(10);
qiTianDaSheng.setHeight(100);
System.out.println("原型对象:" + qiTianDaSheng);
// 开始克隆 - 浅克隆
QiTianDaSheng cloneQiTianDaSheng = (QiTianDaSheng) qiTianDaSheng.clone();
System.out.println("克隆对象:" + cloneQiTianDaSheng);
// clone start compare
System.out.println("\n原型对象中的引用类型地址值:" + qiTianDaSheng.getJinGuBang());
System.out.println("克隆对象中的引用类型地址值:" + cloneQiTianDaSheng.getJinGuBang());
System.out.println("原型对象引用类型地址值 compare 克隆对象引用类型地址值:" + (qiTianDaSheng.getJinGuBang() == cloneQiTianDaSheng.getJinGuBang()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
原型模式 - 浅克隆 总结:
从测试结果以及上图可以清楚看出,浅克隆只是完整的复制了值类型数据,而引用对象仍然指向原来的对象,意味着复制的不是值,而是引用的地址。
在实际开发中,往往我们需要的是完整的复制原型对象(值类型 and 引用类型)。
显然,浅克隆是无法满足我们日常的需求,这时候,深克隆方式就该闪亮登场了...
四、原型模式 - 深克隆
接下来 小主将采用 【鸣人多重影分身术】的案例来阐述原型模式之 深克隆方式:
定义一个(原型对象)鸣人 Naruto 类:
@Getter
@Setter
public class Naruto implements Cloneable, Serializable { // 重点:实现序列化接口
private String name;
private int age;
private List ninjutsu; // 忍术集合
public Object deepClone() {
try {
// write
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// read
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Naruto clone = (Naruto) ois.readObject();
// close stream
bos.close();
oos.close();
bis.close();
ois.close();
// return
return clone;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
return deepClone();
}
public Naruto(String name, int age) {
this.name = name;
this.age = age;
// 忍术
this.ninjutsu = new ArrayList