原型(Prototype)设计模式 1.0.0:什么是原型? ????用一个已经创建的对象,通过复制的手段创建一个和原对象相同或者相似的对象。 2.0.0:为什么要用原型? 对象创建的时间消耗要大于克隆
原型(Prototype)设计模式
1.0.0:什么是原型?
????用一个已经创建的对象,通过复制的手段创建一个和原对象相同或者相似的对象。
2.0.0:为什么要用原型?
- 对象创建的时间消耗要大于克隆(clone)的消耗?reason?
- 对象创建的时候是一个初始态,克隆是一个瞬时态。比如就是,你需要创建一个person,new 的话,person是一个初始态 A,你可能对person进行修改(update),修改之后person的状态发生了改变为 B。那么如果进行克隆的话,你的状态会停留在当前的状态。这就是clone和new的区别。在不同情况,可以分别处理。
- clone会保留对象的状态信息,数据和原对象是一致的,如果对象中含有引用类型的数据的话,那么他的指向地址是一样的,那么比如说有对象A和他的克隆者B。A对他的引用类型进行修改,同时也会影响到B。
eg:A对象有一只鸡,他把鸡杀了,鸡处于死亡状态,那么他的克隆对象的鸡也会死亡。哈哈哈,在某些时候,我们不想他们一样,那么就是需要重新创建新的鸡的引用,存放在堆内存中的数据也就是不同的。如何做?
num 对象的深复制 - 序列化方式--> 序列化 --> 反序列化
- 手动方式--> 所有的引用对象都实现cloneable --> 很麻烦,而且有一些基础类也没有实现cloneable
num 引用的重新创建和指定,引用比较多的时候,会比较麻烦
3.0.0原型的实现代码
3.1.0 浅克隆
@Setter
@Getter
@Slf4j
public class ProtoType implements Cloneable {
private int id;
private String name;
private Attribute attribute;
@Override
public String toString() {
return "ProtoType(" + this.hashCode() + "){" +
"id=" + id +
", name='" + name + '\'' + name.hashCode() +
", attribute=" + attribute +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Setter
@Getter
protected class Attribute {
private int level;
private String love;
@Override
public String toString() {
return "Attribute(" + this.hashCode() + "){" +
"level=" + level +
", love='" + love + '\'' + love.hashCode() +
'}';
}
}
}
@Slf4j
public class ProtoTypeTest {
public static void main(String[] args) {
ProtoType protoType = new ProtoType();
protoType.setId(1);
protoType.setName("alice");
ProtoType.Attribute attribute = protoType.new Attribute();
attribute.setLevel(1);
attribute.setLove("[email protected]");
protoType.setAttribute(attribute);
log.info("protoType {}", protoType);
try {
Object clone = protoType.clone();
log.info("clone {}", clone);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
//run 001
//protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//clone ProtoType(340870931){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//run 002
//protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//clone ProtoType(340870931){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//run 003
//protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
//clone ProtoType(340870931){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
}
}
3.2.0 深克隆
3.2.1 序列化深克隆
@Setter
@Getter
@Slf4j
public class ProtoType implements Cloneable, Serializable {
private int id;
private String name;
private Attribute attribute;
@Override
public String toString() {
int i = this.hashCode();
log.info("----{}", System.identityHashCode(this));
return "ProtoType(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
"id=" + id +
", name='" + name + '\'' + name.hashCode() +
", attribute=" + attribute +
'}';
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
@Setter
@Getter
protected class Attribute implements Serializable {
private int level;
private String love;
@Override
public String toString() {
int i = this.hashCode();
return "Attribute(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
"level=" + level +
", love='" + love + '\'' + love.hashCode() +
'}';
}
}
}
@Slf4j
public class ProtoTypeDeepTest {
public static void main(String[] args) {
ProtoType protoType = new ProtoType();
protoType.setId(1);
protoType.setName("alice");
ProtoType.Attribute attribute = protoType.new Attribute();
attribute.setLevel(1);
attribute.setLove("[email protected]");
protoType.setAttribute(attribute);
log.info("protoType {}", protoType);
ProtoType p2 = new ProtoType();
try {
Object clone = protoType.deepClone();
log.info("clone {}", clone);
} catch (Exception e) {
e.printStackTrace();
}
/**run1
protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
*/
/** run2
protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
*/
/** run3
protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
*/
/** run4 增加 ProtoType p2 = new ProtoType()之后 内存地址也一样
protoType ProtoType(752848266){id=1, name='alice'92903040, attribute=Attribute(815033865){level=1, love='[email protected]'-1847814268}}
clone ProtoType(359023572){id=1, name='alice'92903040, attribute=Attribute(305808283){level=1, love='[email protected]'-1847814268}}
*/
//涉及到的一点 内存的分配规则
}
}
3.2.2 手动深克隆
@Setter
@Getter
@Slf4j
public class ProtoType implements Cloneable {
private int id;
private String name;
private Attribute attribute;
@Override
public Object clone() throws CloneNotSupportedException {
ProtoType clone = (ProtoType) super.clone();
clone.setAttribute(attribute.clone());
return clone;
}
public Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
@Override
public String toString() {
return "ProtoType(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
"id=" + id +
", name='" + name + '\'' + name.hashCode() +
", attribute=" + attribute +
'}';
}
@Setter
@Getter
protected class Attribute implements Cloneable {
private int level;
private String love;
@Override
protected Attribute clone() throws CloneNotSupportedException {
return (Attribute) super.clone();
}
@Override
public String toString() {
return "Attribute(" + this.hashCode() + "|||" + System.identityHashCode(this) + "){" +
"level=" + level +
", love='" + love + '\'' + love.hashCode() +
'}';
}
}
}
@Slf4j
public class ProtoTypeDeepTest2 {
public static void main(String[] args) {
ProtoType protoType = new ProtoType();
protoType.setId(1);
protoType.setName("alice");
ProtoType.Attribute attribute = protoType.new Attribute();
attribute.setLevel(1);
attribute.setLove("[email protected]");
protoType.setAttribute(attribute);
log.info("protoType {}", protoType);
try {
Object clone = protoType.clone();
log.info("clone {}", clone);
} catch (Exception e) {
e.printStackTrace();
}
/**
*protoType ProtoType(752848266|||752848266){id=1, name='alice'92903040, attribute=Attribute(815033865|||815033865){level=1, love='[email protected]'-1847814268}}
*clone ProtoType(340870931|||340870931){id=1, name='alice'92903040, attribute=Attribute(1768305536|||1768305536){level=1, love='[email protected]'-1847814268}}
*
*protoType ProtoType(752848266|||752848266){id=1, name='alice'92903040, attribute=Attribute(815033865|||815033865){level=1, love='[email protected]'-1847814268}}
*clone ProtoType(340870931|||340870931){id=1, name='alice'92903040, attribute=Attribute(1768305536|||1768305536){level=1, love='[email protected]'-1847814268}}
*/
}
}
