什么是原型模式
站在用户的角度思考问题,与客户深入沟通,找到龙沙网站设计与龙沙网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:网站设计制作、成都网站制作、企业官网、英文网站、手机端网站、网站推广、国际域名空间、网页空间、企业邮箱。业务覆盖龙沙地区。
所谓原型模式,就是用原型实例来指定创建对象的种类,并通过复制这些原型创建新的对象的设计模式。原型模式一般用于创建复杂的或者构建耗时的实例,或者用于只读对象的修改。
原型模式的实现方式
(1)浅拷贝
当代的每个程序员小时候都玩过《尤里的复仇》这款游戏,游戏中的“尤里”阵营有个兵种叫“尤里复制人”,每个尤里复制人都和尤里长得一模一样,除了没有坐骑之外。
public classYuri{
privateStringname="Yuri";
privateArrayListwords=newArrayList<>();
public voidsetName(String name) { this.name= name; }
public voidaddWord(String word){ this.words.add(word); }
@Override protectedYuri clone(){ try{ return(Yuri)super.clone(); }catch(CloneNotSupportedException e){ return null; } }
@Override publicString toString() { return"Yuri{"+ "name='"+name+'\''+ ", words="+words.toString() + '}'; } } |
如上,重写了clone()方法。在执行如下代码时:
Yuri yuri =newYuri(); 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");
Log.e("yuri_copyer",yuri_copyer.toString()); Log.e("yuri",yuri.toString());
|
会惊奇地发现两行Log一模一样,这是因为这种原型模式的实现方式只拷贝其引用,换句话说就是并没有将原型对象中的所有字段都重新构造一份,只是用复制对象的字段引用原型对象中的字段,因此被称为“浅拷贝”或“影子拷贝”。
(2)深拷贝
我们把上文的clone()方法修改一下:
@Override protectedYuri clone(){ try{ Yuri copyer = (Yuri)super.clone(); copyer.name=this.name; copyer.words= (ArrayList)this.words.clone(); returncopyer; }catch(CloneNotSupportedException e){ return null; } } |
如上,这种实现方式调用了的clone()方法,这样可以保证副本被修改时不影响原始对象,因此被称为“深拷贝”,又叫做“保护性拷贝”。
Android源码中的原型模式
(1)ArrayList
严格来说ArrayList并不算是Android源码中的类,但应该是Android开发者最常用的类,ArrayList的clone()代码如下:
/** * Returns a shallow copy of thisArrayList instance. (The * elements themselves are not copied.) * *@returna clone of thisArrayList instance */ publicObject clone() { try{ ArrayList> v = (ArrayList>)super.clone(); v.elementData = Arrays.copyOf(elementData,size); v.modCount=0; returnv; }catch(CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw newInternalError(e); } } |
大家可以看到size并没有被clone,因为size是基础类型而不是引用类型,所以不需要clone。细心的读者可以看到注释里面的“shallow copy”,但这实际上是一个典型的深拷贝。
(3)Intent
Android系统加入Intent机制的意义在于大大降低了Android四大组件之间的耦合度。Intent的clone()代码如下:
@Override publicObject clone() { return newIntent(this); } /** * Copy constructor. */ publicIntent(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=newArraySet(o.mCategories); } if(o.mExtras !=null) { this.mExtras=newBundle(o.mExtras); } if(o.mSourceBounds !=null) { this.mSourceBounds=newRect(o.mSourceBounds); } if(o.mSelector !=null) { this.mSelector=newIntent(o.mSelector); } if(o.mClipData !=null) { this.mClipData=newClipData(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】责任链模式——曹瞒兵败走华容
本文标题:【设计模式与Android】原型模式——复制中心走出来的克隆人
网站链接:
http://dzwzjz.com/article/pjhgpi.html