一、原型模式是什么?
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。专业称呼为“CV大法”。
对于java中,复制对象的困难在我们很可能复制了当前对象,但是对象内的引用却只是拿来了,内部深层的对象没有重新创建,所以复制出的对象和原对象存在共用的部分,相互影响。也就是所谓的浅克隆和深克隆。本文只考虑深克隆。这种克隆的功能可以使单独的工具类,也可以是对象自身功能,这里只演示对象自身功能。
二、java代码实现原型模式
原型类(需要实现序列化接口)
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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| package create.prototype;
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.List;
import com.alibaba.fastjson.JSON; /** * * @author bunny~~我是兔子我会喵,我叫喵星兔。 * 原型模式 */ public class MyPrototype implements Serializable {
private static final long serialVersionUID = 1L; private String name; private int age; private List<String> title; /** * 通过序列化实现深度克隆 * @return */ public MyPrototype copyByIO() { 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 (MyPrototype)ois.readObject(); }catch (Exception e){ e.printStackTrace(); return null; } } /** * 通过json实现深度克隆 * @return */ public MyPrototype copyByJson() { try { String jsonString = JSON.toJSONString(this); return (MyPrototype) JSON.parseObject(jsonString, this.getClass()); } catch (Exception e) { e.printStackTrace(); } return null; } 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 List<String> getTitle() { return title; } public void setTitle(List<String> title) { this.title = title; } @Override public String toString() { return "MyPrototype [name=" + name + ", age=" + age + ", title=" + title + "]"; }
}
|
测试类
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
| package create.prototype;
import java.util.ArrayList; import java.util.List;
public class Test {
public static void main(String[] args) { MyPrototype p0 = new MyPrototype(); p0.setAge(11); p0.setName("kitty"); List<String> title = new ArrayList<>(); p0.setTitle(title ); System.out.println(p0); MyPrototype p1 = p0.copyByIO(); p1.getTitle().add("p1"); System.out.println(p0); System.out.println(p1); System.out.println(p0 == p1); System.out.println(p0.getTitle() == p1.getTitle()); MyPrototype p2 = p0.copyByJson(); p2.getTitle().add("p2"); System.out.println(p0); System.out.println(p2); System.out.println(p0 == p2); System.out.println(p0.getTitle() == p2.getTitle()); }
}
|
三、总结
原型模式在编码过程中,绝对是所有设计模式出场频率最高的一种。正所谓“我们不是代码的生产者,我们只是代码的搬运工”。平时我们如果有一个需求,比如上传文件。这时我们不会找到相应的工具,然后去阅读操作手册(就是new对象的过程),而是找寻一个上传样例,用一种叫“CV”的技术实现在我们的代码中(原型模式),进而根据具体的环境进行调试,最终实现功能。
经典之中亦是不少原型的出现,比如“三人行必有我师”、“前事不忘后事之师”。但是是否选择原型还需进一步考虑。因为原型也不是万能的,原型的成功案例很多,但是失败的也是不少。如果各方面允许,其实不使用原型必然是安全的,当然可能不高效。当我们对对象目标了解程度足够高时,选择原型必然是事半功倍。任何的设计模式只要我们足够的掌控,都是我们手中的利器。在掌控不足的情况下也必然是手中的噩梦。