[关闭]
@linux1s1s 2019-02-18T11:27:53.000000Z 字数 3180 阅读 855

Base Time-Design Patterns-Prototype

Base 2017-01


在阎宏博士的《JAVA与模式》一书中开头是这样描述原型(Prototype)模式的:

原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。这就是选型模式的用意。

UML

为了表达清楚上面枯燥的表达,我们用UML类图来说明一下:

此处输入图片的描述

接下来看看源码:

Code

抽象原型角色Contract.java

  1. public interface Contract {
  2. Contract clone();
  3. String getName();
  4. void setName(String name);
  5. }

具体实现角色PrototypeA.java

  1. public class PrototypeA implements Contract {
  2. private String name;
  3. @Override
  4. public Contract clone() {
  5. PrototypeA a = new PrototypeA();
  6. a.setName(name);
  7. return a;
  8. }
  9. @Override
  10. public String getName() {
  11. return name;
  12. }
  13. @Override
  14. public String toString() {
  15. return "PrototypeA " + "[hashcode=" + hashCode() + "] " + "[name=" + name + "]";
  16. }
  17. @Override
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21. }

具体角色实现类PrototypeB.java

  1. public class PrototypeB implements Contract {
  2. private String name;
  3. @Override
  4. public Contract clone() {
  5. PrototypeB b = new PrototypeB();
  6. b.setName(name);
  7. return b;
  8. }
  9. @Override
  10. public String toString() {
  11. return "PrototypeB " + "[hashcode=" + hashCode() + "] " + "[name=" + name + "]";
  12. }
  13. @Override
  14. public String getName() {
  15. return name;
  16. }
  17. @Override
  18. public void setName(String name) {
  19. this.name = name;
  20. }
  21. }

原型管理类PrototypeManager.java

  1. public class PrototypeManager {
  2. private static PrototypeManager INSTANCE;
  3. private final Map<String, Contract> mContracts;
  4. private PrototypeManager() {
  5. mContracts = new HashMap<String, Contract>();
  6. }
  7. public static PrototypeManager getInstance() {
  8. if (INSTANCE == null) {
  9. synchronized (PrototypeManager.class) {
  10. if (INSTANCE == null) {
  11. INSTANCE = new PrototypeManager();
  12. }
  13. }
  14. }
  15. return INSTANCE;
  16. }
  17. public boolean put(String id, Contract c) {
  18. if (TextUtils.isEmpty(id) || c == null) {
  19. return false;
  20. }
  21. if (mContracts.containsKey(id)) {
  22. return false;
  23. }
  24. mContracts.put(id, c);
  25. return true;
  26. }
  27. public Contract get(String id) {
  28. if (TextUtils.isEmpty(id)) {
  29. return null;
  30. }
  31. return mContracts.get(id);
  32. }
  33. public boolean remove(String id) {
  34. if (TextUtils.isEmpty(id)) {
  35. return false;
  36. }
  37. if (!mContracts.containsKey(id)) {
  38. return true;
  39. }
  40. mContracts.remove(id);
  41. return true;
  42. }
  43. }

测试用例TestCase.java

  1. public class TestCase {
  2. public static void exe() {
  3. try {
  4. Contract c1 = new PrototypeA();
  5. PrototypeManager.getInstance().put("p1", c1);
  6. // 获取原型来创建对象
  7. Contract c3 = PrototypeManager.getInstance().get("p1").clone();
  8. c3.setName("susan");
  9. Log.i("Prototype", "第一个实例:" + c3);
  10. // 有人动态的切换了实现
  11. Contract c2 = new PrototypeB();
  12. PrototypeManager.getInstance().put("p1", c2);
  13. // 重新获取原型来创建对象
  14. Contract c4 = PrototypeManager.getInstance().get("p1").clone();
  15. c4.setName("bili");
  16. Log.i("Prototype", "第二个实例:" + c4);
  17. // 有人注销了这个原型
  18. PrototypeManager.getInstance().remove("p1");
  19. // 再次获取原型来创建对象
  20. Contract c5 = PrototypeManager.getInstance().get("p1").clone();
  21. c5.setName("coqi");
  22. Log.i("Prototype", "第三个实例:" + c5);
  23. } catch (NullPointerException e) {
  24. // TODO: handle exception
  25. }
  26. }
  27. }

验证结果

  1. 01-11 06:17:03.053 13654-13654/? I/Prototype: 第一个实例:PrototypeA [hashcode=1384349684] [name=susan]
  2. 01-11 06:17:03.057 13654-13654/? I/Prototype: 第二个实例:PrototypeA [hashcode=1384350260] [name=bili]

附录:深度clone

  1. public Object deepClone() throws IOException, ClassNotFoundException{
  2. //将对象写到流里
  3. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  4. ObjectOutputStream oos = new ObjectOutputStream(bos);
  5. oos.writeObject(this);
  6. //从流里读回来
  7. ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
  8. ObjectInputStream ois = new ObjectInputStream(bis);
  9. return ois.readObject();
  10. }

小结

原型模式要求对象实现一个可以“克隆”自身的接口,这样就可以通过复制一个实例对象本身来创建一个新的实例。这样一来,通过原型实例创建新的对象,就不再需要关心这个实例本身的类型,只要实现了克隆自身的方法,就可以通过这个方法来获取新的对象,而无须再去通过new来创建。

参考博文:
《JAVA与模式》之原型模式

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注