Java23种设计模式系列——创建者模式之原型模式day2-2
原型模式
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象
原型模式包含如下角色:
- 抽象原型类:规定了具体原型对象必须实现的的clone ()方法
- 具体原型类:实现抽象原型类的clone ()方法,它是可被复制的对象
- 访问类:使用具体原型类中的clone ()方法来复制新的对象
原型模式分类
- 深克隆:创建一个对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址(完全独立的一个对象,引用类型有自己的内存地址)
- 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址(非完全独立,其引用类型若克隆对象修改会影响原型对象)
如何实现克隆
Object类中的clone()
方法实现浅克隆
Cloneabel接口的实现标志当前类是可被克隆的
String不是基本类型但可以浅克隆
String是采用(字符串池)string pool的方式,当修改值后会把地址返回,不同的字符串其地址不相同,如果字符串池中有该字符串,会直接返回地址;如果没有,会在池中重新创建一个并返回地址。因为修改后其地址不一样,所以不会影响原来的值
浅克隆示例
- 原型必须实现Cloneable接口
- 重写Object类的clone方法,修改类型
- 浅克隆的引用数据类型的修改会影响原先的原型
- 克隆出来的对象与原型并不是一个对象(内存地址不同)
克隆原型(Man)
package builder_pattern.clone;
public class Man implements Cloneable{
private String name;
private int age;
private double height;
private Life life;
public Man() {
this.name = "张三";
this.age = 29;
this.height = 177.5D;
this.life = new Life();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Life getLife() {
return life;
}
public void setLife(Life life) {
this.life = life;
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
", life=" + life +
'}';
}
@Override
protected Man clone() throws CloneNotSupportedException {
System.out.println("对原型进行克隆");
return (Man) super.clone();
}
}
Man中的引用类型(Life)
package builder_pattern.clone;
public class Life {
private String LifeStyle;
public Life() {
this.LifeStyle = "peace";
}
public void setLifeStyle(String lifeStyle) {
LifeStyle = lifeStyle;
}
public String getLifeStyle() {
return LifeStyle;
}
@Override
public String toString() {
return "Life{" +
"LifeStyle='" + LifeStyle + '\'' +
'}';
}
}
测试类
package builder_pattern.clone;
public class CloneMachine {
public static void main(String[] args) throws CloneNotSupportedException {
//创建原型
Man man = new Man();
//进行克隆
Man clone = man.clone();
System.out.println(clone==man);
System.out.println("原型:"+man.toString());
System.out.println("克隆:"+clone.toString());
//对克隆对象修改
clone.setName("李四");
clone.setAge(21);
clone.setHeight(169.8D);
Life life = clone.getLife();
life.setLifeStyle("mass");
clone.setLife(life);
System.out.println("原型:"+man.toString());
System.out.println("修改后的克隆:"+clone.toString());
}
}
结果
深克隆(序列化方式)
通过序列化和反序列化实现
- 原型类和引用类必须实现Serializable接口
- 使用
ByteArrayInputStream 和 ByteArrayOutputStream
结合ObjectInputStream 和 ObjectOutputStream
进行克隆
Man(原型类)
package builder_pattern.clone.deep;
import java.io.Serializable;
public class Man implements Serializable {
private String name;
private int age;
private double height;
private Life life;
public Man() {
this.name = "张三";
this.age = 29;
this.height = 177.5D;
this.life = new Life();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Life getLife() {
return life;
}
public void setLife(Life life) {
this.life = life;
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
", age=" + age +
", height=" + height +
", life=" + life +
'}';
}
}
引用类型
package builder_pattern.clone.deep;
import java.io.Serializable;
public class Life implements Serializable {
private String LifeStyle;
public Life() {
this.LifeStyle = "peace";
}
public void setLifeStyle(String lifeStyle) {
LifeStyle = lifeStyle;
}
public String getLifeStyle() {
return LifeStyle;
}
@Override
public String toString() {
return "Life{" +
"LifeStyle='" + LifeStyle + '\'' +
'}';
}
}
测试
package builder_pattern.clone.deep;
import java.io.*;
public class CloneMachine {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
//创建原型
Man man = new Man();
//序列化
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
objectOutputStream.writeObject(man);
//反序列化,进行克隆
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
Man cloneMan = (Man) objectInputStream.readObject();
Life life = cloneMan.getLife();
life.setLifeStyle("mass");
cloneMan.setLife(life);
System.out.println(man.toString());
System.out.println(cloneMan.toString());
System.out.println(cloneMan == man);
}
}