[关闭]
@Tyhj 2019-01-29T09:23:34.000000Z 字数 1674 阅读 481

原型模式

设计模式


定义

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

使用场景

  • 类的初始化需要消耗非常多的数据、硬件资源,通过拷贝来避免消耗
  • new 一个对象非常的麻烦,可能需要各种权限
  • 一个对象需要给其他对象使用,而且会被改变,为了保护这个对象,可以使用原型模式

理解

其实就是复制一个已存在的实例,来避免重新创建对象的一些麻烦。但是有时候使用拷贝不一定更高效,需要自己来判断是否使用

实现方法

实现其实很简单,只需要这个类实现Cloneable接口,然后重写一下clone方法就好了,Cloneable接口只是一个标志接口,没有任何方法,clone方法是Object自带的方法,实现了接口才能使用clone方法

举个栗子

随便写个文档的类,保存标题、介绍、图片这些内容,实现Cloneable接口,然后重写一下clone

  1. public class Essay implements Cloneable{
  2. private String title;
  3. private String introduction;
  4. private ArrayList<String> imgs;
  5. @Override
  6. protected Object clone() throws CloneNotSupportedException {
  7. return super.clone();
  8. }
  9. ...
  10. }

初始化后,拷贝这个类

  1. String title = "原型模式";
  2. String introduction = "介绍一";
  3. ArrayList<String> imgs = new ArrayList<>();
  4. imgs.add("图片一");
  5. Essay essay = new Essay(title, introduction, imgs);
  6. Essay essay1= (Essay) essay.clone();
  7. System.out.println(essay1.toString());

输出拷贝对象如下,其实不重写clone方法也完全可以拷贝出来,就是说默认就会拷贝变量

Essay{title='原型模式', introduction='介绍一', imgs=[图片一]}

但是我们改一下程序,把拷贝过来的对象的值改变一下,再输出原对象的值

  1. essay1.imgs.add("嘿嘿嘿");
  2. System.out.println(essay.toString());

输出如下,发现原imgs的值被改变了

Essay{title='原型模式', introduction='介绍一', imgs=[图片一, 嘿嘿嘿]}

这个表明,拷贝的对象只是一个引用了原对象的变量而已,当拷贝对象发生了变化,原对象也变了;

浅拷贝

拷贝的对象只是一个引用了原对象的变量,这个就是浅拷贝;在我们改变了拷贝对象的值的时候,原对象也会改变;

深拷贝

深拷贝肯定就是真正意义上的拷贝,拷贝对象不会对原对象产生影响,方法也很简单;我们可以看到其实基本类型是没有引用的,所以拷贝的时候肯定是没有问题的,不用考虑的基本类型;所以只需要在拷贝对象的时候,对于引用型的字段也采用拷贝的形式就可以了;

  1. @Override
  2. protected Object clone() throws CloneNotSupportedException {
  3. Essay essayClone= (Essay) super.clone();
  4. essayClone.imgs= (ArrayList<String>) imgs.clone();
  5. return essayClone;
  6. }

再次运行,原对象的值的确没有被改变

Essay{title='原型模式', introduction='介绍一', imgs=[图片一]}

但是其中有一个问题就是,如果改变拷贝的String对象的值,原值会不会被改变;其实是不会的,String类比较特殊,因为String是在内存中不可以被改变的对象,String自身没有方法可以改变自身的值;所以要是你的类没有可以改变自身值,也可以不用考虑,本质还是引用,如果用==来判断会返回true

总结

使用原型模式就是为了更高效的创建对象,最好是使用深拷贝,避免影响原始对象

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注