什么是原型模式程序员
所谓原型模式,就是用原型实例来指定建立对象的种类,并经过复制这些原型建立新的对象的设计模式。原型模式通常用于建立复杂的或者构建耗时的实例,或者用于只读对象的修改。设计模式
原型模式的实现方式app
(1)浅拷贝ide
当代的每一个程序员小时候都玩过《尤里的复仇》这款游戏,游戏中的“尤里”阵营有个兵种叫“尤里复制人”,每一个尤里复制人都和尤里长得如出一辙,除了没有坐骑以外。函数
public class Yuri{
private String name = "Yuri";
private ArrayList<String> words = new ArrayList<>();
public void setName(String name) { this.name = name; }
public void addWord(String word){ this.words.add(word); }
@Override protected Yuri clone(){ try{ return (Yuri) super.clone(); }catch (CloneNotSupportedException e){ return null; } }
@Override public String toString() { return "Yuri{" + "name='" + name + '\'' + ", words=" + words.toString() + '}'; } }this |
如上,重写了clone()方法。在执行以下代码时:spa
Yuri yuri = new Yuri(); yuri.setName("Yuri"); yuri.addWord("My name is Yuri"); yuri.addWord("You mind is clear");
Yuri yuri_copyer = yuri.clone(); yuri.setName("Yuri's copyer");设计 yuri.addWord("I'm not the only one true Yuri");orm
Log.e("yuri_copyer",yuri_copyer.toString()); Log.e("yuri",yuri.toString());对象
|
会惊奇地发现两行Log如出一辙,这是由于这种原型模式的实现方式只拷贝其引用,换句话说就是并无将原型对象中的全部字段都从新构造一份,只是用复制对象的字段引用原型对象中的字段,所以被称为“浅拷贝”或“影子拷贝”。
(2)深拷贝
咱们把上文的clone()方法修改一下:
@Override protected Yuri clone(){ try{ Yuri copyer = (Yuri) super.clone(); copyer.name = this.name; copyer.words = (ArrayList<String>)this.words.clone(); return copyer; }catch (CloneNotSupportedException e){ return null; } } |
如上,这种实现方式调用了的clone()方法,这样能够保证副本被修改时不影响原始对象,所以被称为“深拷贝”,又叫作“保护性拷贝”。
Android源码中的原型模式
(1)ArrayList
严格来讲ArrayList并不算是Android源码中的类,但应该是Android开发者最经常使用的类,ArrayList的clone()代码以下:
/** * Returns a shallow copy of this <tt>ArrayList</tt> instance. (The * elements themselves are not copied.) * * @return a clone of this <tt>ArrayList</tt> instance */ public Object clone() { try { ArrayList<?> v = (ArrayList<?>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(e); } } |
你们能够看到size并无被clone,由于size是基础类型而不是引用类型,因此不须要clone。细心的读者能够看到注释里面的“shallow copy”,但这其实是一个典型的深拷贝。
(3)Intent
Android系统加入Intent机制的意义在于大大下降了Android四大组件之间的耦合度。Intent的clone()代码以下:
@Override public Object clone() { return new Intent(this); } /** * Copy constructor. */ public Intent(Intent o) { this.mAction = o.mAction; this.mData = o.mData; this.mType = o.mType; this.mPackage = o.mPackage; this.mComponent = o.mComponent; this.mFlags = o.mFlags; this.mContentUserHint = o.mContentUserHint; if (o.mCategories != null) { this.mCategories = new ArraySet<String>(o.mCategories); } if (o.mExtras != null) { this.mExtras = new Bundle(o.mExtras); } if (o.mSourceBounds != null) { this.mSourceBounds = new Rect(o.mSourceBounds); } if (o.mSelector != null) { this.mSelector = new Intent(o.mSelector); } if (o.mClipData != null) { this.mClipData = new ClipData(o.mClipData); } } |
Intent的clone()内部并无调用super.clone(),而是调用了new Intent(this)。
Android开发中如何利用原型模式
(1)Object的clone()方法直接操做二进制流,效率很是高。在对象的初始化要消耗很是多的资源时,或者用new来实例化一个对象时须要很是繁琐的数据准备或访问权限时,可使用原型模式提升效率、避免消耗资源。
(2)对深拷贝生成的副本进行修改不会影响原始对象。当一个对象会被不一样对象用不一样方式修改时,能够用原型模式产生副本供调用者使用。
须要注意的几个问题
(1)原型模式在clone()的时候不会从新执行构造函数,可能会出现问题。
(2)在某些对象构造很是简单的状况下,好比上文提到的Intent,从新new一个比clone()快,所以不要滥用原型模式
本系列其余博客
【设计模式与Android】工厂方法模式——化工女神的工厂
【设计模式与Android】抽象工厂模式——嵌合体克隆工厂
【设计模式与Android】策略模式——锦囊里的上策中策下策
【设计模式与Android】状态模式——一我的的两幅面孔
【设计模式与Android】责任链模式——曹瞒兵败走华容