1. 定义

原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

2. 实现

2.1 Cloneable接口clone方法

2.1.1 Product

实现Cloneable接口clone方法,clone方法中编写深拷贝逻辑

  1. class Product implements Cloneable {
  2. private String part1;
  3. private String part2;
  4. private String part3;
  5. private String part4;
  6. private Info info;
  7. public Product(String part1, String part2, String part3, String part4, Info info) {
  8. this.part1 = part1;
  9. this.part2 = part2;
  10. this.part3 = part3;
  11. this.part4 = part4;
  12. this.info = info;
  13. }
  14. public String getPart1() {
  15. return part1;
  16. }
  17. public void setPart1(String part1) {
  18. this.part1 = part1;
  19. }
  20. public String getPart2() {
  21. return part2;
  22. }
  23. public void setPart2(String part2) {
  24. this.part2 = part2;
  25. }
  26. public String getPart3() {
  27. return part3;
  28. }
  29. public void setPart3(String part3) {
  30. this.part3 = part3;
  31. }
  32. public String getPart4() {
  33. return part4;
  34. }
  35. public void setPart4(String part4) {
  36. this.part4 = part4;
  37. }
  38. public Info getInfo() {
  39. return info;
  40. }
  41. public void setInfo(Info info) {
  42. this.info = info;
  43. }
  44. @Override
  45. public String toString() {
  46. return this.hashCode() + " Product{" +
  47. "part1='" + part1 + '\'' +
  48. ", part2='" + part2 + '\'' +
  49. ", part3='" + part3 + '\'' +
  50. ", part4='" + part4 + '\'' +
  51. ", info=" + info +
  52. '}';
  53. }
  54. @Override
  55. protected Product clone() throws CloneNotSupportedException {
  56. //深拷贝
  57. Product clone = (Product) super.clone();
  58. Info info = this.info.clone();
  59. clone.setInfo(info);
  60. return clone;
  61. }
  62. }

Info作为product的属性,同样实现Cloneable的clone方法,以便实现深拷贝

  1. class Info implements Cloneable {
  2. private String name;
  3. public Info(String name) {
  4. this.name = name;
  5. }
  6. public String getName() {
  7. return name;
  8. }
  9. public void setName(String name) {
  10. this.name = name;
  11. }
  12. @Override
  13. public String toString() {
  14. return this.hashCode() + " prototype.Info{" +
  15. "name='" + name + '\'' +
  16. '}';
  17. }
  18. @Override
  19. protected Info clone() throws CloneNotSupportedException {
  20. return (Info) super.clone();
  21. }
  22. }

2.1.2 使用及测试

  1. public static void main(String[] args) throws CloneNotSupportedException {
  2. Info info1 = new Info("info1");
  3. Product product = new Product("part1", "part2", "part3", "part4", info1);
  4. //clone
  5. Product clone = product.clone();
  6. //打印对比
  7. System.out.println("original: "+product);
  8. System.out.println("clone: "+clone);
  9. //打印结果:可以看到hashcode 不一样,说明已经实现了深拷贝
  10. // original: 460141958 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=1163157884 prototype.Info{name='info1'}}
  11. // clone: 1956725890 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=356573597 prototype.Info{name='info1'}}
  12. //修改info打印对比
  13. product.getInfo().setName("info2");
  14. System.out.println("original: "+product);
  15. System.out.println("clone: "+clone);
  16. // 打印结果:修改原始product.info后,clone.info没有变化,说明实现了深拷贝
  17. // original: 460141958 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=1163157884 prototype.Info{name='info2'}}
  18. // clone: 1956725890 Product{part1='part1', part2='part2', part3='part3', part4='part4', info=356573597 prototype.Info{name='info1'}}
  19. }

2.2 序列化机制实现(不推荐)

修改clone实现逻辑

  1. @Override
  2. protected Product clone() throws CloneNotSupportedException {
  3. //深拷贝
  4. // Product clone = (Product) super.clone();
  5. // Info info = this.info.clone();
  6. // clone.setInfo(info);
  7. // return clone;
  8. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  9. try (ObjectOutputStream oss = new ObjectOutputStream(byteArrayOutputStream)) {
  10. oss.writeObject(this);
  11. } catch (IOException e) {
  12. e.printStackTrace();
  13. }
  14. ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
  15. try (ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream)) {
  16. Product product = null;
  17. product = (Product) ois.readObject();
  18. return product;
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. } catch (ClassNotFoundException e) {
  22. e.printStackTrace();
  23. }
  24. return null;
  25. }

3. 应用场景

当代码不应该依赖于需要复制的对象的具体类时,请使用Prototype模式 。

4. 优点

  1. 可以不耦合具体类的情况下克隆对象
  2. 避免重复的初始化代码
  3. 更方便的构建复杂对象

    5. Spring源码中的应用

    1. org.springframework.beans.factory.support.AbstractBeanDefinition
    2. java.util.Arrays