原型模式
原型模式(Prototype Pattern)属于创建型模式,主要用于创建重复的对象,我们通常创建重复对象的时候都是通过set方法一个一个copy属性值的,这样如果类中属性特别多的话非常不好用,而且效率也不高在日常开发中,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public void submitRepair(RepairForm repairForm) { Repair repair = new Repair(); repair.setAppraisal(repairForm.getAppraisal()); repair.setContent(repairForm.getContent()); repair.setReply(repairForm.getReply()); repair.setReplyTime(repairForm.getReplyTime()); repair.setStarNum(repairForm.getStarNum()); repair.setState(repairForm.getState()); repair.setVisitTime(repairForm.getVisitTime()); repair.setTime(repairForm.getCreateTime()); repair.setTitle(RepairTypeEnums.getTextByType(repairForm.getType())); xxxService.submit(repair); }
|
这样的代码,一旦类属性过多,就会显得很臃肿,而原型模式,能帮助我们解决这样的问题。
简介
原型模式(Prototype Pattern)是指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式主要适用于以下场景:
在 Spring 中,原型模式应用得非常广泛。例如 scope=“prototype”,在我们经常用 的 JSON.parseObject()也是一种原型模式。下面,我们来看看原型模式类结构图:
简单克隆
简单原型模式的设计代码如下:
1 2 3
| public interface Prototype { Prototype clone(); }
|
有多个可以使用类似的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class PrototypeA implements Prototype {
private int age; private String name; private List hobbies;
@Override public Prototype clone() { PrototypeA concretePrototype = new PrototypeA(); concretePrototype.setAge(this.age); concretePrototype.setName(this.name); concretePrototype.setHobbies(this.hobbies); return concretePrototype; } }
|
1 2 3 4 5 6 7 8 9 10 11
| public class Client { private Prototype prototype;
public Client(Prototype prototype) { this.prototype = prototype; }
public Prototype startClone(Prototype concretePrototype) { return (Prototype) concretePrototype.clone(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class PrototypeTest { public static void main(String[] args) { PrototypeA concretePrototype = new PrototypeA(); concretePrototype.setAge(18); concretePrototype.setName("prototype"); List hobbies = new ArrayList<String>(); concretePrototype.setHobbies(hobbies); System.out.println(concretePrototype);
Client client = new Client(concretePrototype); PrototypeA concretePrototypeClone = (PrototypeA) client.startClone(concretePrototype); System.out.println(concretePrototypeClone); System.out.println("克隆对象中的引用类型地址值:" + concretePrototypeClone.getHobbies()); System.out.println("原对象中的引用类型地址值:" + concretePrototype.getHobbies()); System.out.println("对象地址比较:" + (concretePrototypeClone.getHobbies() == concretePrototype.getHobbies())); } }
|
1 2 3 4 5
| com.design.pattern.prototype.simple.PrototypeA@24d46ca6 com.design.pattern.prototype.simple.PrototypeA@4517d9a3 克隆对象中的引用类型地址值:[] 原对象中的引用类型地址值:[] 对象地址比较:true
|
从测试结果看出 hobbies 的引用地址是相同的,意味着复制的不是值,而是引用的地址。 这样的话,如果我们修改任意一个对象中的属性值,concretePrototype 和 concretePrototypeCone 的 hobbies 值都会改变,这个就是我们说的浅克隆。
深克隆
我们知道公司的员工除了自己的信息以外,都会有一个工位,但是每个人的工位都是不相同的,我们用深克隆来实现这个场景。
1 2 3 4
| public class StaffInfo { public String name; public int age; }
|
1 2 3 4 5 6
| public class Station implements Serializable { public String area; public String number; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class Staff extends StaffInfo implements Serializable, Cloneable { public Station station;
public Staff() { station = new Station(); }
@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); Staff copy = (Staff) ois.readObject(); return copy; } catch (Exception e) { e.printStackTrace(); return null; } }
public Staff shallowClone(Staff target) { Staff staff = new Staff(); staff.age = target.age; staff.name = target.name; staff.station = target.station; return staff; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class DeepCloneTest {
public static void main(String[] args) { Staff staff = new Staff(); try { Staff clone = (Staff) staff.clone(); System.out.println("深克隆:" + (staff.station == clone.station)); } catch (Exception e) { e.printStackTrace(); } Staff q = new Staff(); Staff n = q.shallowClone(q); System.out.println("浅克隆:" + (q.station == n.station)); } }
|