💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## **模式的定义** 用已经创建的原型实例来指定创建对象的种类,并通过拷贝这些原型创建新的对象并完成初始化。 白话文就是说通过new一个实例,在对这个new的实例进行拷贝来创建新的实例。 原型模式分为**浅复制**和**深复制**2种方式 ## **浅复制** 浅拷贝需要实现`java.lang.Cloneable`接口,然后再调用`Object`类中的`clone`方法 1. 创建复制对象的类 ``` public class Book implements Cloneable { private String title; private int number; private ArrayList<String> images = new ArrayList<>(); // get set ... public void addImages(String imgName) { this.images.add(imgName); } @Override public Book clone() { Book book = new Book(); try { // 调用Object父类的clone方法 book = (Book) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return book; } // 打印输出 public void show() { System.out.println("title:" + title); System.out.println("number:" + number); String imageStr = ""; for (String image : images) { imageStr = imageStr + "," + image; } System.out.println("images:" + imageStr); System.out.println("----------------"); } } ``` 2. 客户端调用 ``` public static void main(String[] args) { Book book1 = new Book(); book1.setTitle("book1"); book1.setNumber(1); book1.addImages("pic1"); book1.show("步骤一"); Book book2 = book1.clone(); book2.show("步骤二"); book2.setTitle("book2"); book2.setNumber(2); book2.addImages("pic2"); book2.show("步骤三"); book1.show("步骤四"); } ``` 3. 结果 ``` 步骤一 title:book1 number:1 images:,pic1 ---------------- 步骤二 title:book1 number:1 images:,pic1 ---------------- 步骤三 title:book2 number:2 images:,pic1,pic2 ---------------- 步骤四 title:book1 number:1 images:,pic1,pic2 ---------------- ``` 步骤一二三应该很好的理解,book2成功的完成了复制的功能,但是步骤四却让人产生了疑虑,book2在改变images值的时候,book1中images的值也发送了改变,这明显不是我们想要的复制结果,通过查找资料发现,浅复制的复制方式 ``` 基本数据类型:复制成员变量以及它的值 引用数据类型:复制成员变量以及它的引用地址的值 ``` Book对象中 * number(int):基本数据类型,复制的时候就是产生一个新的副本 * images(ArrayList):引用数据类型,复制完后book2中images引用地址的值和book1中的是相同的,book1和book2中的images引用的是同一个引用对象,我们在操作images时,都是对同一个引用对象进行改变,所以就导致了步骤四的问题 * title(String):引用数据类型,为什么就没问题呢?String对象用的final修饰,是一个不可变的对象,每次修改它的值都是会改变它的引用对象(而不是对它的引用对象进行改变) ## **深复制** 为了解决上面浅复制引用数据类型的问题,Java提供了深复制的功能来完成引用类型数据的复制 只需要在上面的代码中修改clone方法 ``` @Override public Book clone() { Book book = new Book(); try { book = (Book) super.clone(); // 代码1 // 深复制 book.images = (ArrayList<String>) this.images.clone(); // 代码2 } catch (CloneNotSupportedException e) { e.printStackTrace(); } return book; } ``` 代码1处调用的clone方法是`Object`类中的提供的原生方法,代码2处调用的底层方法是`System`类中的`arraycopy`原生方法。