经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
创建型设计模式 -- 原型模式
来源:cnblogs  作者:累成一条狗  时间:2019/8/15 12:15:00  对本文有异议

一、小案例分析

1、功能需求:

  现有一个员工,姓名为Rick,年龄22,ID为193211,如何创建10个完全相同的对象。

2、小菜鸡的答案:

(1)直接new 10个对象就完了。
(2)代码实现:

  1. package prototype.pattern;
  2. public class Demo {
  3. public static void main(String[] args) {
  4. Employee employee = new Employee("Tom", 22, 193211);
  5. Employee employee1 = new Employee("Tom", 22, 193211);
  6. Employee employee2 = new Employee("Tom", 22, 193211);
  7. Employee employee3 = new Employee("Tom", 22, 193211);
  8. Employee employee4 = new Employee("Tom", 22, 193211);
  9. Employee employee5 = new Employee("Tom", 22, 193211);
  10. Employee employee6 = new Employee("Tom", 22, 193211);
  11. Employee employee7 = new Employee("Tom", 22, 193211);
  12. Employee employee8 = new Employee("Tom", 22, 193211);
  13. Employee employee9 = new Employee("Tom", 22, 193211);
  14. System.out.println(employee);
  15. System.out.println(employee1);
  16. System.out.println(employee2);
  17. System.out.println(employee3);
  18. System.out.println(employee4);
  19. System.out.println(employee5);
  20. System.out.println(employee6);
  21. System.out.println(employee7);
  22. System.out.println(employee8);
  23. System.out.println(employee9);
  24. }
  25. }
  26. class Employee {
  27. private String name;
  28. private int age;
  29. private long ID;
  30. public Employee(String name, int age, long ID) {
  31. super();
  32. this.name = name;
  33. this.age = age;
  34. this.ID = ID;
  35. }
  36. public String getName() {
  37. return name;
  38. }
  39. public void setName(String name) {
  40. this.name = name;
  41. }
  42. public int getAge() {
  43. return age;
  44. }
  45. public void setAge(int age) {
  46. this.age = age;
  47. }
  48. public long getID() {
  49. return ID;
  50. }
  51. public void setID(long iD) {
  52. ID = iD;
  53. }
  54. @Override
  55. public String toString() {
  56. return "Employee [name=" + name + ", age=" + age + ", ID=" + ID + "]";
  57. }
  58. }

(3)代码分析:
  容易理解,好操作。但是每次都是初始化对象,而不是动态获得对象,不够灵活,效率低。

二、原型模式

1、什么是原型模式

  指的是用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。是一种创建模式,允许一个对象去创建另一个可定制的对象且不用知道如何创建的细节。

2、如何实现(影分身之术)

  将一个原型对象传给 发动创建的对象,此对象通过请求原型对象拷贝自身来进行创建,即调用clone方法。

3、clone方法、浅拷贝、深拷贝

  可以参照如下地址:
    https://www.cnblogs.com/l-y-h/p/10906499.html#_label1
注:
  上面链接中只讲述了通过clone方法实现深拷贝(所有涉及到的类均要实现Cloneable接口)。
  也可以使用序列化的方式实现深拷贝(推荐,所有涉及到的类均要实现Serializable接口)。

  1. package prototype.pattern;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectInputStream;
  6. import java.io.ObjectOutputStream;
  7. import java.io.Serializable;
  8. public class Demo {
  9. public static void main(String[] args) {
  10. Employee employee = new Employee("Tom", 22, 193211);
  11. Employee employee2 = (Employee) employee.deepClone();
  12. System.out.println(employee);
  13. System.out.println(employee2);
  14. }
  15. }
  16. // 此处若不实现Serializable 接口,会抛出java.lang.NullPointerException异常。
  17. class Person implements Serializable {
  18. private String name;
  19. private int age;
  20. public Person(String name, int age) {
  21. super();
  22. this.name = name;
  23. this.age = age;
  24. }
  25. public String getName() {
  26. return name;
  27. }
  28. public void setName(String name) {
  29. this.name = name;
  30. }
  31. public int getAge() {
  32. return age;
  33. }
  34. public void setAge(int age) {
  35. this.age = age;
  36. }
  37. @Override
  38. public String toString() {
  39. return "Person [name=" + name + ", age=" + age + "]";
  40. }
  41. }
  42. class Employee implements Serializable {
  43. private String name;
  44. private int age;
  45. private long ID;
  46. private Person people = new Person("Jarry", 20);
  47. public Employee(String name, int age, long ID) {
  48. super();
  49. this.name = name;
  50. this.age = age;
  51. this.ID = ID;
  52. }
  53. public String getName() {
  54. return name;
  55. }
  56. public void setName(String name) {
  57. this.name = name;
  58. }
  59. public int getAge() {
  60. return age;
  61. }
  62. public void setAge(int age) {
  63. this.age = age;
  64. }
  65. public long getID() {
  66. return ID;
  67. }
  68. public void setID(long iD) {
  69. ID = iD;
  70. }
  71. @Override
  72. public String toString() {
  73. return "Employee [name=" + name + ", age=" + age + ", ID=" + ID + "]";
  74. }
  75. /**
  76. * 使用序列化的方式实现深拷贝
  77. *
  78. * @return
  79. */
  80. public Object deepClone() {
  81. ByteArrayOutputStream baos = null;
  82. ObjectOutputStream oos = null;
  83. ByteArrayInputStream bias = null;
  84. ObjectInputStream ois = null;
  85. try {
  86. // 序列化
  87. baos = new ByteArrayOutputStream();
  88. oos = new ObjectOutputStream(baos);
  89. oos.writeObject(this); // 将当前对象以对象流的方式输出
  90. // 反序列化
  91. bias = new ByteArrayInputStream(baos.toByteArray());
  92. ois = new ObjectInputStream(bias);
  93. Employee employee = (Employee) ois.readObject();
  94. return employee;
  95. } catch (Exception e) {
  96. System.out.println(e.getMessage());
  97. return null;
  98. } finally {
  99. try {
  100. baos.close();
  101. oos.close();
  102. bias.close();
  103. ois.close();
  104. } catch (IOException e) {
  105. System.out.println(e.getMessage());
  106. }
  107. }
  108. }
  109. }

4、使用原型模式实现上例

(1)使原型类实现 Cloneable 接口(只有实现该接口,才能重写clone方法)。
(2)调用原型对象自身的clone方法实现拷贝。
(3)代码实现:

  1. package prototype.pattern;
  2. public class Demo {
  3. public static void main(String[] args) {
  4. Employee employee = new Employee("Tom", 22, 193211);
  5. Employee employee1 = (Employee) employee.clone();
  6. Employee employee2 = (Employee) employee.clone();
  7. Employee employee3 = (Employee) employee.clone();
  8. Employee employee4 = (Employee) employee.clone();
  9. Employee employee5 = (Employee) employee.clone();
  10. Employee employee6 = (Employee) employee.clone();
  11. Employee employee7 = (Employee) employee.clone();
  12. Employee employee8 = (Employee) employee.clone();
  13. Employee employee9 = (Employee) employee.clone();
  14. System.out.println(employee);
  15. System.out.println(employee1);
  16. System.out.println(employee2);
  17. System.out.println(employee3);
  18. System.out.println(employee4);
  19. System.out.println(employee5);
  20. System.out.println(employee6);
  21. System.out.println(employee7);
  22. System.out.println(employee8);
  23. System.out.println(employee9);
  24. }
  25. }
  26. class Employee implements Cloneable {
  27. private String name;
  28. private int age;
  29. private long ID;
  30. public Employee(String name, int age, long ID) {
  31. super();
  32. this.name = name;
  33. this.age = age;
  34. this.ID = ID;
  35. }
  36. public String getName() {
  37. return name;
  38. }
  39. public void setName(String name) {
  40. this.name = name;
  41. }
  42. public int getAge() {
  43. return age;
  44. }
  45. public void setAge(int age) {
  46. this.age = age;
  47. }
  48. public long getID() {
  49. return ID;
  50. }
  51. public void setID(long iD) {
  52. ID = iD;
  53. }
  54. @Override
  55. public String toString() {
  56. return "Employee [name=" + name + ", age=" + age + ", ID=" + ID + "]";
  57. }
  58. @Override
  59. protected Object clone() {
  60. Employee employee = null;
  61. try {
  62. employee = (Employee) super.clone();
  63. } catch (CloneNotSupportedException e) {
  64. System.out.println(e.getMessage());
  65. }
  66. return employee;
  67. }
  68. }

(3)代码分析:
  让程序有更好的扩展性与效率,当修改某个原型对象时,其余clone后的对象均会被修改。
(4)UML图:

 

5、使用原型模式的优缺点

(1)优点:当创建新的对象比较复杂时,使用原型模式可以简化创建流程、且提高创建的效率。不需要重新new对象,而是动态的获取运行中的对象。
(2)缺点:当实现深拷贝的clone方法时,需要给所有涉及到的类加个clone方法,可能会违反开闭原则。

 

三、Spring中原型模式分析

1、bean的创建

  在创建bean的时候,可以选择是单例模式(同一对象) 还是原型模式(不同对象)。

2、部分源码:(稍后整理)

原文链接:http://www.cnblogs.com/l-y-h/p/11348377.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号