5、原型模式
原型模式是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,属于创建型模式。
创建原型接口
package com.jdwa.prototype;
public interface IPrototype<T> {
T clone();
}
创建具体的需要克隆的对象:
package com.jdwa.prototype;
public class ConcretePrototype implements IPrototype {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "ConcretePrototype{" +
"age=" + age +
", name=‘" + name + ‘\‘‘ +
‘}‘;
}
@Override
public ConcretePrototype clone() {
ConcretePrototype concretePrototype = new ConcretePrototype();
concretePrototype.setAge(this.age);
concretePrototype.setName(this.name);
return concretePrototype;
}
}
测试代码:
package com.jdwa.prototype;
public class Client {
public static void main(String[] args) {
ConcretePrototype concretePrototype = new ConcretePrototype();
concretePrototype.setName("TOM");
concretePrototype.setAge(25);
ConcretePrototype cloneProtoType = concretePrototype.clone();
System.out.println(concretePrototype);
System.out.println(cloneProtoType);
}
}
当然了,上面的方法不用我们自己实现,JDK已经帮我们实现好了,只需要实现一下Cloneable接口。
package com.jdwa.prototype;
import lombok.Data;
@Data
public class ConcreteProtoType2 implements Cloneable {
private int age;
private String name;
@Override
protected ConcreteProtoType2 clone() {
try {
return (ConcreteProtoType2) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "ConcreteProtoType2{" +
"age=" + age +
", name=‘" + name + ‘\‘‘ +
‘}‘;
}
}
但是当原型对象属性包含对象如List时,修改克隆对象同时原型对象也会被修改,这就是我们常说的浅克隆,这显然不符合我们遇到的大部分场景。
浅克隆只是复制了值类型数据,没有复制引用对象。这就需要用到深克隆了。
使用序列化进行深克隆
package com.jdwa.prototype;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;
import lombok.Data;
import java.io.*;
import java.util.List;
@Data
public class ConcretePrototype3 implements Cloneable, Serializable {
private int age;
private String name;
private List<String> hobbis;
@Override
protected ConcretePrototype3 clone() {
try {
return (ConcretePrototype3) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}
public ConcretePrototype3 deepClone(){
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (ConcretePrototype3) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
@Override
public String toString() {
return "ConcretePrototype3{" +
"age=" + age +
", name=‘" + name + ‘\‘‘ +
", hobbis=" + hobbis +
‘}‘;
}
}
测试代码:
package com.jdwa.prototype;
import java.util.ArrayList;
import java.util.List;
public class Client {
public static void main(String[] args) {
// testSimpleClone();
deepClone();
/*
原型:ConcretePrototype3{age=25, name=‘TOM‘, hobbis=[游泳, 跑步]}
克隆:ConcretePrototype3{age=25, name=‘TOM‘, hobbis=[游泳, 跑步, 俯卧撑]}
false
原型的爱好:[游泳, 跑步]
克隆的爱好:[游泳, 跑步, 俯卧撑]
false
*/
}
private static void testSimpleClone(){
ConcretePrototype concretePrototype = new ConcretePrototype();
concretePrototype.setName("TOM");
concretePrototype.setAge(25);
ConcretePrototype cloneProtoType = concretePrototype.clone();
System.out.println(concretePrototype);
System.out.println(cloneProtoType);
}
private static void deepClone(){
ConcretePrototype3 concretePrototype3 = new ConcretePrototype3();
concretePrototype3.setAge(25);
concretePrototype3.setName("TOM");
List<String> hobbis = new ArrayList<>(3);
hobbis.add("游泳");
hobbis.add("跑步");
concretePrototype3.setHobbis(hobbis);
ConcretePrototype3 cloneObj = concretePrototype3.deepClone();
cloneObj.getHobbis().add("俯卧撑");
System.out.println("原型:"+concretePrototype3);
System.out.println("克隆:"+cloneObj);
System.out.println(concretePrototype3 == cloneObj);
System.out.println("原型的爱好:"+concretePrototype3.getHobbis());
System.out.println("克隆的爱好:"+cloneObj.getHobbis());
System.out.println(concretePrototype3.getHobbis() == cloneObj.getHobbis());
}
}
当然也可以使用json序列化与反序列化实现