简介

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。

优点: 1、性能提高。 2、逃避构造函数的约束。
缺点: 1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。 2、必须实现 Cloneable 接口。

浅拷贝与深拷贝

在实现Cloneable接口时,进行拷贝对象,效率比构造函数要高,也避免了构造传参的麻烦。
拷贝对象分为浅拷贝和深拷贝,默认的Object.clone()是浅拷贝。浅拷贝只能复制基本数据类型和基本数据类型的包装类,以及特殊的String类。如果是复杂的引用类型,浅拷贝会直接拷贝引用,如果原始对象修改了引用对象内部属性的值,所有拷贝的对象的值会跟着变,这会引发安全问题。

也就是说,当对象的属性中包含复杂的对象时,要使用深拷贝,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。

简单的深拷贝实现是,在对象的每一层中都调用clone方法,即可实现深拷贝,即每层对象浅拷贝 = 深拷贝。如果对象层次比较多,调用clone会很复杂,这时可以使用序列化,再反序列化回来的方式进行深拷贝,另外通过序列化为json字符串,然后从json字符串转回来也是比较常用的方式。

应用实例

克隆羊,通过clone方法进行复制多个对象,这里使用浅拷贝就可以。

  1. package com.mori.design.pattern.prototype;
  2. /**
  3. * 羊
  4. * @author mori
  5. */
  6. public class Sheep implements Cloneable{
  7. private String name;
  8. private Integer age;
  9. private String color;
  10. public Sheep(String name, Integer age, String color) {
  11. super();
  12. this.name = name;
  13. this.age = age;
  14. this.color = color;
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. public int getAge() {
  23. return age;
  24. }
  25. public void setAge(Integer age) {
  26. this.age = age;
  27. }
  28. public String getColor() {
  29. return color;
  30. }
  31. public void setColor(String color) {
  32. this.color = color;
  33. }
  34. /**
  35. * 克隆该实例,使用默认的clone方法来完成
  36. */
  37. @Override
  38. public Sheep clone() {
  39. Sheep sheep = null;
  40. try {
  41. sheep = (Sheep)super.clone();
  42. } catch (Exception e) {
  43. e.printStackTrace();
  44. }
  45. return sheep;
  46. }
  47. @Override
  48. public String toString() {
  49. return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
  50. }
  51. }

测试代码如下

  1. public void testSheep(){
  2. Sheep sheep = new Sheep("小样", 12, "白色");
  3. Sheep sheep2 = sheep.clone();
  4. Sheep sheep3 = sheep.clone();
  5. Sheep sheep4 = sheep.clone();
  6. System.out.println(sheep);
  7. System.out.println(sheep2);
  8. System.out.println(sheep3);
  9. System.out.println(sheep4);
  10. }

控制台输出:

  1. Sheep [name=小样, age=12, color=白色]
  2. Sheep [name=小样, age=12, color=白色]
  3. Sheep [name=小样, age=12, color=白色]
  4. Sheep [name=小样, age=12, color=白色]