经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
23种设计模式之原型模式
来源:cnblogs  作者:锻心  时间:2019/8/2 8:51:36  对本文有异议

原型模式

1、基本介绍

1)原型模式(Prototype模式)是指:用原型实例指定创建对象的种类,并通过拷贝这些原型,创建新的对象。
2)原型模式是一种创建型设计模式,允许一个对象再创建另一个可定制的对象,而无需知道如何创建的细节。
3)原理:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建,即 对象.clone()。
4)结论:使用原型模式使程序有更高的效率和扩展性。
5)类图:

  1. Prototype:原型类,声明一个克隆自己的接口。
  2. ConcretePrototype:具体的原型类,实现一个克隆自己的操作。
  3. Client:让一个原型对象克隆自己,从而创建一个新的对象(属性一样)

6)代码:

  

  1. // 原型类
  2. public class Sheep implements Cloneable {
  3.  
  4. private String name;
  5. private Integer age;
  6. private String color;
  7.  
  8. public Sheep() {
  9. }
  10.  
  11. public Sheep(String name, Integer age, String color) {
  12. this.name = name;
  13. this.age = age;
  14. this.color = color;
  15. }
  16.  
  17. public String getName() {
  18. return name;
  19. }
  20.  
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24.  
  25. public Integer getAge() {
  26. return age;
  27. }
  28.  
  29. public void setAge(Integer age) {
  30. this.age = age;
  31. }
  32.  
  33. public String getColor() {
  34. return color;
  35. }
  36.  
  37. public void setColor(String color) {
  38. this.color = color;
  39. }
  40.  
  41. @Override
  42. public String toString() {
  43. return "Sheep{" +
  44. "name='" + name + '\'' +
  45. ", age=" + age +
  46. ", color='" + color + '\'' +
  47. '}';
  48. }
  49.  
  50. /**
  51. * 克隆该实例,使用默认的clone方法来完成
  52. * @param []
  53. * @date 2019/7/30 15:40
  54. * @return java.lang.Object
  55. **/
  56. @Override
  57. protected Object clone() {
  58. Sheep sheep = null;
  59. try {
  60. sheep = (Sheep) super.clone();
  61. } catch (CloneNotSupportedException e) {
  62. e.printStackTrace();
  63. }
  64. return sheep;
  65. }
  66. }
  67.  
  68. // Client
  69. public class Client {
  70. public static void main(String[] args) {
  71. Sheep sheep = new Sheep("Tom", 1, "白色");
  72.  
  73. // 使用克隆
  74. Sheep sheep2 = (Sheep) sheep.clone();
  75. Sheep sheep3 = (Sheep) sheep.clone();
  76. Sheep sheep4 = (Sheep) sheep.clone();
  77. Sheep sheep5 = (Sheep) sheep.clone();
  78.  
  79. System.out.println(sheep);
  80. System.out.println(sheep2);
  81. System.out.println(sheep3);
  82. System.out.println(sheep4);
  83. System.out.println(sheep5);
  84. }
  85. }
  86.  
  87. /*
  88. 结果:
  89. Sheep{name='Tom', age=1, color='白色'}
  90. Sheep{name='Tom', age=1, color='白色'}
  91. Sheep{name='Tom', age=1, color='白色'}
  92. Sheep{name='Tom', age=1, color='白色'}
  93. Sheep{name='Tom', age=1, color='白色'}
  94. */

  

2、浅拷贝和深拷贝

2.1、浅拷贝的介绍

1)对于数据类型是基本数据类型(包含String)的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。
2)对于数据类型是引用数据类型的成员变量,比如是数组、某个类的对象,那么浅拷贝会进行引用传递,实际就是两个对象的该成员变量指向同一个实例。在这种情况下,在一个对象修改该成员变量时,会影响到另一个对象的该成员变量值。
3)代码中的克隆羊例子就是浅拷贝。
4)浅拷贝是使用默认的clone()方法来实现

2.2、深拷贝的介绍

1)复制对象的所有基本数据类型(包含String)的成员变量值。
2)为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象进行拷贝。
3)实现1:重写clone方法
4)实现2:通过对象序列化(推荐,实现看代码)

2.3、代码

  1. // DeepCloneableTarget
  2. public class DeepCloneableTarget implements Serializable, Cloneable {
  3.  
  4. private static final long serialVersionUID = 1L;
  5.  
  6. private String cloneName;
  7. private String cloneClass;
  8.  
  9. public DeepCloneableTarget(String cloneName, String cloneClass) {
  10. this.cloneName = cloneName;
  11. this.cloneClass = cloneClass;
  12. }
  13.  
  14. /**
  15. * 该类中成员变量都是基本属性类型,所以使用默认clone方法
  16. * */
  17. @Override
  18. protected Object clone() throws CloneNotSupportedException {
  19. return super.clone();
  20. }
  21.  
  22. @Override
  23. public String toString() {
  24. return "DeepCloneableTarget{" +
  25. "cloneName='" + cloneName + '\'' +
  26. ", cloneClass='" + cloneClass + '\'' +
  27. '}';
  28. }
  29. }
  30.  
  31. // DeepPrototype
  32. public class DeepPrototype implements Serializable, Cloneable {
  33.  
  34. /** String数据类型 */
  35. private String name;
  36. /** 引用数据类型 */
  37. private DeepCloneableTarget target;
  38.  
  39. public DeepPrototype() {
  40. }
  41.  
  42. public String getName() {
  43. return name;
  44. }
  45.  
  46. public void setName(String name) {
  47. this.name = name;
  48. }
  49.  
  50. public DeepCloneableTarget getTarget() {
  51. return target;
  52. }
  53.  
  54. public void setTarget(DeepCloneableTarget target) {
  55. this.target = target;
  56. }
  57.  
  58. /**
  59. * 深拷贝方式一:使用clone方法
  60. * */
  61. @Override
  62. protected Object clone() throws CloneNotSupportedException {
  63. Object deep = null;
  64. // 完成基本数据类型(属性)和String类型的克隆
  65. deep = super.clone();
  66.  
  67. // 对引用类型属性进行单独处理
  68. DeepPrototype deepPrototype = (DeepPrototype) deep;
  69. deepPrototype.target = (DeepCloneableTarget) target.clone();
  70.  
  71. return deepPrototype;
  72. }
  73.  
  74. /**
  75. * 深拷贝方式二:通过对象的序列化(推荐)
  76. * */
  77. public Object deepClone() {
  78. // 创建流对象
  79. ByteArrayOutputStream bos = null;
  80. ObjectOutputStream oos = null;
  81. ByteArrayInputStream bis = null;
  82. ObjectInputStream ois = null;
  83. // 创建该类对象
  84. DeepPrototype clone = null;
  85. try {
  86. // 序列化
  87. bos = new ByteArrayOutputStream();
  88. oos = new ObjectOutputStream(bos);
  89. oos.writeObject(this);
  90.  
  91. // 反序列
  92. bis = new ByteArrayInputStream(bos.toByteArray());
  93. ois = new ObjectInputStream(bis);
  94. clone = (DeepPrototype) ois.readObject();
  95. } catch (Exception e) {
  96. e.printStackTrace();
  97. } finally {
  98. // 关闭资源
  99. try {
  100. if (bos != null) {
  101. bos.close();
  102. }
  103. if (oos != null) {
  104. oos.close();
  105. }
  106. if (bis != null) {
  107. bis.close();
  108. }
  109. if (ois != null) {
  110. ois.close();
  111. }
  112. } catch (Exception e) {
  113. e.printStackTrace();
  114. }
  115. }
  116. return clone;
  117. }
  118.  
  119. @Override
  120. public String toString() {
  121. return "DeepPrototype{" +
  122. "name='" + name + '\'' +
  123. ", target=" + target +
  124. '}';
  125. }
  126. }
  127.  
  128. // Client
  129. public class Client {
  130. public static void main(String[] args) throws CloneNotSupportedException {
  131. DeepPrototype deepPrototype = new DeepPrototype();
  132. deepPrototype.setName("tom");
  133. deepPrototype.setTarget(new DeepCloneableTarget("cloneName", "cloneClass"));
  134.  
  135. // 通过clone方法实现深拷贝
  136. DeepPrototype deepPrototype1 = (DeepPrototype) deepPrototype.clone();
  137.  
  138. System.out.println("通过clone方法实现深拷贝");
  139. System.out.println(deepPrototype + "" + deepPrototype.getTarget().hashCode());
  140. System.out.println(deepPrototype1 + "" + deepPrototype1.getTarget().hashCode());
  141.  
  142. System.out.println("------------------------------");
  143.  
  144. // 通过序列化实现深拷贝
  145. DeepPrototype deepPrototype2 = (DeepPrototype) deepPrototype.deepClone();
  146. System.out.println("通过序列化实现深拷贝");
  147. System.out.println(deepPrototype + "" + deepPrototype.getTarget().hashCode());
  148. System.out.println(deepPrototype2 + "" + deepPrototype2.getTarget().hashCode());
  149. }
  150. }


  151. /*
  152. // 结果:
  153. 通过clone方法实现深拷贝
  154. DeepPrototype{name='tom', target=DeepCloneableTarget{cloneName='cloneName', cloneClass='cloneClass'}}460141958
  155. DeepPrototype{name='tom', target=DeepCloneableTarget{cloneName='cloneName', cloneClass='cloneClass'}}1163157884
  156. ------------------------------
  157. 通过序列化实现深拷贝
  158. DeepPrototype{name='tom', target=DeepCloneableTarget{cloneName='cloneName', cloneClass='cloneClass'}}460141958
  159. DeepPrototype{name='tom', target=DeepCloneableTarget{cloneName='cloneName', cloneClass='cloneClass'}}1791741888
    */

  

3、原型模式的注意事项和细节

1)创建新对象比较复杂时,可以利用原型模式简化对象的创建,同时提高效率。
2)不用重新初始化对象,而是动态的获取对象运行时的状态。
3)如果原始对象发生变化(增加或减少对象),其他克隆对象就会随之变化,无需修改代码。
4)在实现深克隆时可能需要交复杂的代码。
5)缺点:需要为每个类配备一个克隆方法,这对全新的类不是难事,但是对已有的类进行改造时,需要修改源代码,违反了ocp原则。

原文链接:http://www.cnblogs.com/dx520/p/11271264.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号