1.原型模式(Prototype)定义:指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

1.Cloneable接口/Object#clone方法详解
2.浅拷贝/深拷贝
3.序列化机制实现深拷贝

2.实现Cloneable接口,重写clone方法实现浅拷贝

  1. class BaseInfo{
  2. private String companyName;
  3. public BaseInfo(String companyName){
  4. this.companyName = companyName;
  5. }
  6. @Override
  7. public String toString() {
  8. return "["+ super.hashCode()+"],companyName:"+companyName;
  9. }
  10. }
  11. class Product implements Cloneable{
  12. private final String mainBoard; //1.先安装主板
  13. private final String cpu; //2.再安装cpu
  14. private final String memory; //3.再安装内存
  15. private BaseInfo baseInfo;
  16. public Product(String mainBoard,String cpu,String memory,BaseInfo baseInfo){
  17. this.mainBoard = mainBoard;
  18. this.cpu = cpu;
  19. this.memory = memory;
  20. this.baseInfo = baseInfo;
  21. }
  22. public Product build(){
  23. /*
  24. 在这里实现组装操作
  25. */
  26. return this;
  27. }
  28. @Override
  29. protected Product clone() throws CloneNotSupportedException {
  30. return (Product) super.clone();
  31. }
  32. @Override
  33. public String toString() {
  34. return "["+ super.hashCode()+"],mainBoard:"+mainBoard+",cpu:"+cpu+",memory:"+memory+",baseInfo:"+baseInfo;
  35. }
  36. }
  37. public class BuilderTest {
  38. public static void main(String[] args) {
  39. BaseInfo baseInfo = new BaseInfo("appple");
  40. Product product = new Product("jiJia","m1","32G",baseInfo).build();
  41. Product product1 = null;
  42. try {
  43. product1 = product.clone();
  44. } catch (CloneNotSupportedException e) {
  45. e.printStackTrace();
  46. }
  47. System.out.println(product);
  48. System.out.println(product1);
  49. }
  50. }

image.png
结果如上图,product和product1的两个类的hascode是不一样的,所以他们两个是不相同的类了,
但引用的其它子类baseInfo却是相同的,也就是product和product1的两个类共用一个引用了,这就是浅拷贝。

3.让引用子类也实现Cloneable接口,并重写clone方法实现深拷贝

  1. class BaseInfo implements Cloneable{
  2. private String companyName;
  3. public BaseInfo(String companyName){
  4. this.companyName = companyName;
  5. }
  6. @Override
  7. protected BaseInfo clone() throws CloneNotSupportedException {
  8. return (BaseInfo) super.clone();
  9. }
  10. @Override
  11. public String toString() {
  12. return "["+ super.hashCode()+"],companyName:"+companyName;
  13. }
  14. }
  15. class Product implements Cloneable{
  16. private final String mainBoard; //1.先安装主板
  17. private final String cpu; //2.再安装cpu
  18. private final String memory; //3.再安装内存
  19. public BaseInfo baseInfo;
  20. public Product(String mainBoard,String cpu,String memory,BaseInfo baseInfo){
  21. this.mainBoard = mainBoard;
  22. this.cpu = cpu;
  23. this.memory = memory;
  24. this.baseInfo = baseInfo;
  25. }
  26. public Product build(){
  27. /*
  28. 在这里实现组装操作
  29. */
  30. return this;
  31. }
  32. @Override
  33. protected Product clone() throws CloneNotSupportedException {
  34. Product clone = (Product) super.clone();
  35. BaseInfo clone1 = this.baseInfo.clone();
  36. clone.baseInfo = clone1;
  37. return clone;
  38. }
  39. @Override
  40. public String toString() {
  41. return "["+ super.hashCode()+"],mainBoard:"+mainBoard+",cpu:"+cpu+",memory:"+memory+",baseInfo:"+baseInfo;
  42. }
  43. }
  44. public class BuilderTest {
  45. public static void main(String[] args) {
  46. BaseInfo baseInfo = new BaseInfo("appple");
  47. Product product = new Product("jiJia","m1","32G",baseInfo).build();
  48. Product product1 = null;
  49. try {
  50. product1 = product.clone();
  51. } catch (CloneNotSupportedException e) {
  52. e.printStackTrace();
  53. }
  54. System.out.println(product);
  55. System.out.println(product1);
  56. }
  57. }

image.png

4.利用java序列化机制实现深拷贝

cpu密集型,会比较消耗cpu的性能,效率没有上面3中的方法效率高。

  1. class BaseInfo implements Serializable{
  2. private static final long serialVersionUID = 42L;
  3. private String companyName;
  4. public BaseInfo(String companyName){
  5. this.companyName = companyName;
  6. }
  7. @Override
  8. public String toString() {
  9. return "["+ super.hashCode()+"],companyName:"+companyName;
  10. }
  11. }
  12. class Product implements Cloneable,Serializable{
  13. private static final long serialVersionUID = 42L;
  14. private final String mainBoard; //1.先安装主板
  15. private final String cpu; //2.再安装cpu
  16. private final String memory; //3.再安装内存
  17. public BaseInfo baseInfo;
  18. public Product(String mainBoard,String cpu,String memory,BaseInfo baseInfo){
  19. this.mainBoard = mainBoard;
  20. this.cpu = cpu;
  21. this.memory = memory;
  22. this.baseInfo = baseInfo;
  23. }
  24. public Product build(){
  25. /*
  26. 在这里实现组装操作
  27. */
  28. return this;
  29. }
  30. @Override
  31. protected Product clone() throws CloneNotSupportedException {
  32. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  33. try(ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);) {
  34. objectOutputStream.writeObject(this);
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }
  38. ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
  39. try(ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);) {
  40. Product product = (Product) objectInputStream.readObject();
  41. return product;
  42. } catch (IOException e) {
  43. e.printStackTrace();
  44. } catch (ClassNotFoundException e) {
  45. e.printStackTrace();
  46. }
  47. return null;
  48. }
  49. @Override
  50. public String toString() {
  51. return "["+ super.hashCode()+"],mainBoard:"+mainBoard+",cpu:"+cpu+",memory:"+memory+",baseInfo:"+baseInfo;
  52. }
  53. }
  54. public class BuilderTest {
  55. public static void main(String[] args) {
  56. BaseInfo baseInfo = new BaseInfo("appple");
  57. Product product = new Product("jiJia","m1","32G",baseInfo).build();
  58. Product product1 = null;
  59. try {
  60. product1 = product.clone();
  61. } catch (CloneNotSupportedException e) {
  62. e.printStackTrace();
  63. }
  64. System.out.println(product);
  65. System.out.println(product1);
  66. }
  67. }

image.png

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

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

Spring源码中的应用
1org.springframework.beans.factory.support.AbstractBeanDefinition
2java.util.Arrays