【设计模式】原型模式(Prototype)

摘要:

1.本文将详细介绍原型模式的原理和实际代码中特别是Android系统代码中的应用。

纲要:

1. 引入原型模式

2. 原型模式的概念及优缺点介绍

3. 原型模式对拷贝的使用

4. 原型模式在Android源码中的应用

1.先来一个段子:

GG和MM经常在QQ上聊天,但是GG打字的速度慢如蜗牛爬行,每次MM在瞬间完成恢复或者问候是,GG都会很紧张的去尽力快速打字,尽管如此,还是让MM有些不高兴,MM说回复信息这么慢,显然是用心不专,不在乎她。哎,GG也是百口难辩啊,不过也确实是没有办法。

有一天,GG想自己的密友K倾诉了自己的苦衷。K顿生大笑。说道:“傻瓜,你怎么不去网上收集一些肉麻的情话以及一些你们经常说话会涉及到主题,把这些东西拷贝下来保存在自己的电脑或者U盘里面,这样一来如果下次在聊天就可以借用过来了!”,“K就是K,我怎么没有想到呢~妙极~妙极^_^”,“不过不要太高兴,这些东西是要适当修改的,要不然你把名字都搞错的话,就等着你的MM把你踹死吧O(∩_∩)O哈哈~”K补充道,“嗯,说的对,谢谢K哥解决了我的心腹之患啊”GG乐不可支的说道。

这是MM由在网上和GG聊天,GG专门复制那些实现准备好的肉麻情话经过稍加修改后发给MM,MM都快美死了…(摘自Android之大话设计模式)

2.原型模式介绍

2.1什么是原型模式?

在类A创建实例的时候,会将传入的类B的实例(这个实例被称为原型对象)进行克隆,以此快速的获得与传入对象一致的初始化数据。克隆是原型模式最显著特点。

类A被称为隔离类,因为原型模式将类A隔离起来,不需要关注类B的变化。

类B称为原型类,实现了clone()接口给类A克隆。类B是易变的,但是实现的接口不易变。类B通常是一个抽象类,传入给类A的实例是类B的子类的实例。

2.2这样做有什么好处?

1、 方便。如果一个原型对象本身数据非常多,一个一个赋值是不现实的。通过进行克隆,我们可以快速的获得这个原型对象的全部数据。

2、 耦合度低。如果原型对象是个“易变类”,即这个类可能会有各种各样的继承,或者这个类随着开发的进行可能会不断的修改。但只要类B实现的接口是稳定不易变的, 原型模式可以使隔离类保持接口的稳定性,不需要随着类的变化而变化。

3.1关于拷贝:

克隆有两种,浅拷贝和深拷贝。浅拷贝就是只克隆一次,对被克隆的类的所有属性进行直接的赋值,而不是递归的克隆。递归的克隆就是对自己的属性也调用它自己的克隆方法。对于基本类型(七种基本类型boolean,char,byte,short,float,double.long)来说,赋值将得到此基本类型的一份拷贝。如果是非基本类型,则得到引用的拷贝。引用的拷贝意味着什么?意味着直接赋值之后,这两个普通类的实例的指向的数据空间是同一个。也就是说它们的修改会互相影响。我们举一个例子:

两个类A,B,它们的属性如下:

Class A {
    int a1;

    String a2;

    B b;

}

Class B {

    int b1;

    String b2;

}

如果我们要实现Class A的浅拷贝,它的clone方法将会是这样的:

Object clone() {

    return super.clone();

}

万类之王Object自己已经实现了clone方法,我们只需要调用就可以了,在这里Object.clone()其实等价于:

A aa = new A();

aa.a1 = this.a1;

aa.a2 = this.a2;

aa.b = this.b;

return a;

当然,这只是等价,不是真正的实现方法,毕竟Object不知道这个Class A有什么属性。万类之王是通过字节拷贝实现的,调用的是native方法。Class B是非基本类型,所以直接赋值只会得到b引用的拷贝,新克隆出来的aa实例和原实例a指向了同一个b实例的数据空间。所以对a.b的改动会影响到原实例a的b改动。

如果是深拷贝,我们应该这样实现:

Object clone() {

    A aa = (A)super.clone();

    aa.b = (B)a.b.clone();

    return (Object)aa;

}

其实就是把非基本类型的属性再进行一次克隆就可以了,如果该属性中仍有非基本类型,则需要同样实现深拷贝。这里也就暴露出原型模式的缺点:实现原型模式的类的属性需要全部实现clone(),否则无法实现该模式。对于一个新创建的类来说也许不难,但如果中后期加入,则会需要大量的改动。

因为Java故意的隐瞒了指针这个概念,导致这里的理解有点复杂。从C语言的角度来看,int,float等类型为基本类型,他们本身在声明的时候就拥有了自己储存值的空间,赋值的时候是把值重新拷贝了一份。而自己定义的struct结构体,我们声明的是对应的struct*指针,不同指针指向同一个内存块,它们的修改会互相影响。

3.2Interger,String等包装类的拷贝问题:

细心的同学可能发现了,String不是基础类型,为什么在上面直接赋值就可以了?String的存储实际上通过char[]来实现的,同样,Interger是int的包装类。包装类的特质之一就是在对其值进行操作时会体现出其对应的基本类型的性质。关于该问题的详细情况可以访问:http://freej.blog.51cto.com/235241/168676。

3.3原型模式使用的是哪种拷贝呢?

设计模式里并没有指定原型模式是采用哪种拷贝,我们应根据实际情况选择深拷贝和浅拷贝。当然深拷贝应用的场景要多很多。此外,拷贝也没有指定需要拷贝所有属性,也是根据实际情况选择就可以了。

4.Android源码实战举例:

例子:Intent

Intent是一个实现了简单的原型模式的类。它的clone是这样的:

@Override

public Object clone() {

    return new Intent(this);

}

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;

    //下面几个是引用对象被重新创建了,是深拷贝

    if (o.mCategories != null) {

        this.mCategories = new HashSet<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是一个深拷贝。有趣的是,它的属性也是使用构造器这种方式进行拷贝。在这种情况下,上文提到的“隔离类”和“易变类”都是自己。

new Intent(Intent o)这种构造方法在源码中屡见不鲜。如Launcher3中的LauncherModel.java,frameworks中的LauncherActivity.java,Settings中的DockEventReceiver。我们可以通过搜索“Intent(intent”或“Intent(mIntent”看到。

版权所有,转载请注明出处:

http://www.cnblogs.com/sickworm/p/4016081.html

时间: 2024-10-13 16:07:46

【设计模式】原型模式(Prototype)的相关文章

谈谈设计模式~原型模式(Prototype)

返回目录 原型模式是创建型模式的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例(clone),而不是新建(new)实例.被复制的实例就是我们所称的“原型”,这个原型是可定制的. 原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效:或者创建值相等,只是命名不一样的同类数据. 从原型模式的概念中,我们可以看到,在这个模式里,拷贝是个很重要的概念,即在不创建对象的情况下,返回一个已有对象,这就是拷贝去实现的,在面向对象的编程世界里,拷贝分为浅拷

[工作中的设计模式]原型模式prototype

一.模式解析 提起prototype,最近看多了js相关的内容,第一印象首先是js的原型 var Person=function(name){ this.name=name; } Person.prototype.run=function(){ alert(this.name+" is running"; } 此处的原型是js的特殊定义,在原型上定义的属性和方法所有的类进行共享. 不过设计模式中的原型模式指的是:将已有的对象作为原型,拷贝出一份具有相同属性的新的对象. 模式定义为:原型

java语言实现创建型设计模式—原型模式(Prototype)

一.描述 原型模式是通过一个原型对象来标明要创建的对象的类型,然后用复制这个原型对象的方法来拷贝创建更多的同类型对象.例如我们在程序的动态运行过程中有了一个对象,这个对象中包含了一系列的有效数据,我们此时需要一个和该对象完全相同的新对象,并且在拷贝之后,新旧对象之间没有任何联系,对任何一个对象的更改都不影响另一个对象. 在java中所有类都默认继承自java.lang.Object类,在这个Object类中有一个clone()方法,该方法将返回Object对象的一个拷贝. 我们让需要被拷贝的类实

设计模式:原型模式(Prototype)

以前听过这样一句话:“程序员的最高境界就是Ctrl+C.Ctrl+V”,我们先不论这句话的对错,就论这个过程,这个过程我们都知道无非就是复制一个对象,然后将其不断地粘贴.这样的过程我们可以将其称之为“克隆”.再如我们应聘的时候打印了那么多的简历. 克隆我们都清楚,就是用一个物体复制若干个一模一样物体.同样,在面向对象系统中,我们同样可以利用克隆技术来克隆出若干个一模一样的对象.在应用程序中,有些对象比较复杂,其创建过程过于复杂,而且我们又需要频繁的利用该对象,如果这个时候我们按照常规思维new该

二十四种设计模式:原型模式(Prototype Pattern)

原型模式(Prototype Pattern) 介绍用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象. 示例有一个Message实体类,现在要克隆它. MessageModel using System; using System.Collections.Generic; using System.Text; namespace Pattern.Prototype { /// <summary> /// Message实体类 /// </summary> publi

深入浅出设计模式——原型模式(Prototype Pattern)

模式动机在面向对象系统中,使用原型模式来复制一个对象自身,从而克隆出多个与原型对象一模一样的对象.在软件系统中,有些对象的创建过程较为复杂,而且有时候需要频繁创建,原型模式通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的意图所在. 模式定义原型模式(Prototype Pattern):原型模式是一种对象创建型模式,用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象.原型模式允许一个对象再创建另外一个可定制的对象,无

10. 星际争霸之php设计模式--原型模式

题记==============================================================================本php设计模式专辑来源于博客(jymoz.com),现在已经访问不了了,这一系列文章是我找了很久才找到完整的,感谢作者jymoz的辛苦付出哦! 本文地址:http://www.cnblogs.com/davidhhuan/p/4248189.html============================================

JAVA 设计模式 原型模式

用途 原型模式 (Prototype) 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 原型模式是一种创建型模式. 结构 图-原型模式结构图 Prototype: 声明一个克隆自身的接口.ConcretePrototype: 实现克隆自身的具体操作.Client: 调用 Prototype 来克隆自身,从而创建一个新对象. 应用场景 当要实例化的类是在运行时刻指定时,例如,通过动态装载.为了避免创建一个与产品类层次平行的工厂类层次时.当一个类的实例只能有几个不同状态组合中的一种

炒冷饭系列:设计模式 原型模式

炒冷饭系列:设计模式 原型模式 摘要: 原创出处: http://www.cnblogs.com/Alandre/ 泥沙砖瓦浆木匠 希望转载,保留摘要,谢谢! 亲爱我,孝何难:亲恶我,孝方贤. 一.什么是原型模式 Prototype模式是一种对象创建型模式,它採取复制原型对象的方法来创建对象的实例.使用 Prototype模式创建的实例,具有与原型一样的 数据. 二.原型模式的特点 1. 由原型对象自身创建目标对象.也就是说,对 象创建这一动作发自原型对象本身. 2.目标对象是原型对象的一个克隆

设计模式--原型模式

原型模式 Prototype Pattern 意图:使用原型实例定义/指定被创建对象种类/类型,通过拷贝原型实例创建新对象 应用场景: 1)当某个类指定在运行时实例化 2)减少子类数量 3)降低昂贵类型新对象创建成本 好处或缺点: 1)clone方法可能实现比较困难 2)不适用于含循环引用的类结构 类结构: 参与者:client ,Prototype,ConcretePrototype prototype:定义原型的行为 //关键代码 class Notification implements