原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用场景:
1.类初始化消耗资源较多。
2.new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)。
3.构造函数比较复杂。
4.循环体中生产大量对象时。
1.浅克隆
定义:
创建一个新对象,新对象的属性和原来对象的属性完全相同,对于引用类型属性,仍指向原有属性所指向的对象的内存地址。
UML类结构图:
代码实现:
Prototype类
public interface Prototype {
Prototype clone();
}
ConcretePrototypeA类
public class ConcretePrototypeA implements Prototype {
private int age;
private String name;
private List hobbies;
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;
}
public List getHobbies() {
return hobbies;
}
public void setHobbies(List hobbies) {
this.hobbies = hobbies;
}
@Override
public Prototype clone() {
ConcretePrototypeA concretePrototypeA = new ConcretePrototypeA();
concretePrototypeA.setAge(this.age);
concretePrototypeA.setHobbies(this.hobbies);
concretePrototypeA.setName(this.name);
return concretePrototypeA;
}
}
Client类
public class Client {
private Prototype prototype;
public Client(Prototype prototype) {
this.prototype = prototype;
}
public Prototype startClone(Prototype prototype) {
return prototype.clone();
}
}
测试代码:
public class PrototypeTest {
public static void main(String[] args) {
// 创建一个具体的需要克隆的对象
ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
// 填充属性,方便测试
concretePrototype.setAge(18);
concretePrototype.setName("prototype");
List<String> hobbies = new ArrayList<>();
concretePrototype.setHobbies(hobbies);
System.out.println(concretePrototype);
// 创建 Client 对象,准备开始克隆
Client client = new Client(concretePrototype);
ConcretePrototypeA concretePrototypeClone = (ConcretePrototypeA) client.startClone(concretePrototype);
System.out.println(concretePrototype);
System.out.println("克隆对象中的引用类型地址值:" + concretePrototypeClone.getHobbies());
System.out.println("原对象中的引用类型地址值:" + concretePrototype.getHobbies());
System.out.println("对象地址比较:" + (concretePrototypeClone.getHobbies() == concretePrototype.getHobbies()));
}
}
运行结果:
com.gupaoedu.vip.pattern.prototype.ConcretePrototypeA@61bbe9ba
com.gupaoedu.vip.pattern.prototype.ConcretePrototypeA@61bbe9ba
克隆对象中的引用类型地址值:[]
原对象中的引用类型地址值:[]
对象地址比较:true
2.深克隆
定义:
创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
(通过序列化和反序列化来实现深克隆)
代码实现:
Monkey类
public class Monkey {
public int height;
public int weight;
public Date birthday;
}
QiTianDaSheng类
public class QiTianDaSheng extends Monkey implements Cloneable, Serializable {
public JinGuBang jinGuBang;
public QiTianDaSheng() {
// 只是初始化
this.birthday = new Date();
this.jinGuBang = new JinGuBang();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return this.deepClone();
}
public Object 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);
QiTianDaSheng copy = (QiTianDaSheng) ois.readObject();
copy.birthday = new Date();
return copy;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public QiTianDaSheng shallowClone(QiTianDaSheng target) {
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
qiTianDaSheng.height = target.height;
qiTianDaSheng.weight = target.weight;
qiTianDaSheng.jinGuBang = target.jinGuBang;
qiTianDaSheng.birthday = target.birthday;
return qiTianDaSheng;
}
}
JinGuBang类
public class JinGuBang implements Serializable {
public float h = 100;
public float d = 10;
public void big() {
this.d *= 2;
this.h *= 2;
}
public void small() {
this.d /= 2;
this.h /= 2;
}
}
测试代码类
public class DeepCloneTest {
public static void main(String[] args) {
QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
try {
QiTianDaSheng clone = (QiTianDaSheng) qiTianDaSheng.clone();
System.out.println("深克隆:" + (qiTianDaSheng.jinGuBang == clone.jinGuBang));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
QiTianDaSheng q = new QiTianDaSheng();
QiTianDaSheng s = q.shallowClone(q);
System.out.println("浅克隆:" + (q.jinGuBang == s.jinGuBang));
}
}