定义:原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。例如,Windows 操作系统的安装通常较耗时,如果复制就快了很多。
    优点:

    1. Java 自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
    2. 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。

    缺点:

    1. 需要为每一个类都配置一个 clone 方法
    2. clone 方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违背了开闭原则。
    3. 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深克隆、浅克隆需要运用得当。

    实现方法:

    1. 实现Cloneable接口
    2. 重写clone()方法(clone是Object类的方法) ```java public class Sheep implements Cloneable{

      private String name ;

      private int age ;

      private Color color;

      public String getName() {

      1. return name;

      }

      public void setName(String name) {

      1. this.name = name;

      }

      public int getAge() {

      1. return age;

      }

      public void setAge(int age) {

      1. this.age = age;

      }

      public Color getColor() {

      1. return color;

      }

      @Override public String toString() {

      1. return "Sheep["+this.hashCode()+"]{" +
      2. "name='" + name + '\'' +
      3. ", age=" + age +
      4. ", color=" + color +
      5. '}';

      }

      public void setColor(Color color) {

    1. this.color = color;
    2. }
    3. // 浅克隆
    4. @Override
    5. protected Object clone(){
    6. try {
    7. return super.clone();
    8. } catch (CloneNotSupportedException e) {
    9. e.printStackTrace();
    10. }
    11. return null;
    12. }

    }

    1. **扩展:**
    2. > 浅拷贝:复制一个对象,复制它的变量时又两种情况:
    3. > - 基本数据类型时直接将值传递
    4. > - 对象是复制的引用值
    5. >
    6. 深拷贝:也会将其里面的对象复制一份。
    7. 上面那方式就是浅拷贝:
    8. ```java
    9. public class Color implements Cloneable{
    10. private String name ;
    11. public String getName() {
    12. return name;
    13. }
    14. public void setName(String name) {
    15. this.name = name;
    16. }
    17. public Color(String name) {
    18. this.name = name;
    19. }
    20. @Override
    21. public String toString() {
    22. return "Color{" +
    23. "name='" + name + '\'' +
    24. '}';
    25. }
    26. @Override
    27. protected Object clone() {
    28. try {
    29. return super.clone();
    30. } catch (CloneNotSupportedException e) {
    31. e.printStackTrace();
    32. }
    33. return null;
    34. }
    35. }
    1. public class Client {
    2. public static void main(String[] args) {
    3. Sheep sheep = new Sheep();
    4. sheep.setName("喜羊羊");
    5. sheep.setAge(3);
    6. Color color = new Color("黑色");
    7. sheep.setColor(color);
    8. Sheep sheep1 = (Sheep) sheep.clone();
    9. System.out.println(sheep);
    10. System.out.println(sheep1);
    11. System.out.println("-------------------------------");
    12. sheep1.setAge(4);
    13. sheep1.setName("美羊羊");
    14. color.setName("白色");
    15. System.out.println(sheep);
    16. System.out.println(sheep1);
    17. }
    18. }

    此时打印结果:
    image.png
    深拷贝:
    有两种方式:

    1. 将里面的对象在复制一遍

      1. // 深克隆
      2. @Override
      3. protected Object clone(){
      4. Sheep sheep = null ;
      5. try {
      6. sheep = (Sheep) super.clone();
      7. sheep.color = (Color) color.clone();
      8. return sheep;
      9. } catch (CloneNotSupportedException e) {
      10. e.printStackTrace();
      11. }
      12. return null;
      13. }

      此时打印结果:
      image.png

    2. 利用序列化来复制对象(推荐) ```java // 深克隆 序列化 @Override protected Object clone() {

      1. Sheep sheep = null;
      2. ByteArrayInputStream bis = null;
      3. ObjectInputStream ois = null;
      4. ByteArrayOutputStream bos = null;
      5. ObjectOutputStream oos = null;
      6. try {
      7. bos = new ByteArrayOutputStream();
      8. oos = new ObjectOutputStream(bos);
      9. oos.writeObject(this);
      10. bis = new ByteArrayInputStream(bos.toByteArray());
      11. ois = new ObjectInputStream(bis);
      12. return ois.readObject();
      13. } catch (Exception e) {
      14. e.printStackTrace();
      15. } finally {
      16. try {
      17. ois.close();
      18. bis.close();
      19. oos.close();
      20. bos.close();
      21. } catch (IOException e) {
      22. e.printStackTrace();
      23. }
      24. }
      25. return null;

      }

    ``` 此时打印的结果:
    image.png
    可以发现两种方法都可以实现对对象内部的对象的拷贝。