005.设计模式之Prototype模式
场景:
在我们使用电脑制作Word文档的时候, 步骤就是先新建/打开一个Word文档, 然后一个一个字的打进文档里面, 按照一定的步骤编辑等, 然后保存文档. 一份Word文档就完成了. 此时有10个人分别要求你给他们看一下你这份文档. 你是不是新建10份Word文档, 重复上面说的步骤操作10遍, 从而生成10份文档给那10个人看呢. 傻瓜才会这么做, 我直接拷贝出10份做好的文档出来不就行了吗.
飞机工厂中, 每做好一架飞机, 需要组装, 调试, 试飞等步骤. 如果有一种方法做好了一架飞机, 组装, 调试, 试飞后, 其他的飞机直接拷贝出来就可以了, 那飞机工厂就省事了. 可是不行的, 毕竟飞机是实物, 每一架飞机都需要经过组装, 调试, 试飞这个过程.
现在我们假设飞机工厂可以拷贝飞机. 那飞机工厂会先做好一架样板机, 样板机还是需要组装, 调试, 试飞. 为了后面的飞机是最好的, 那样板机可能要组装得最好, 调试到最好, 试飞数据要最好的. 经过辛苦的样板机组装, 调试, 试飞后, 飞机工厂就可以拿样板机做拷贝了.
老板说:“给我盖一座大楼。”
工程师说:“盖什么样的大楼呢?”
老板指着身后的一座楼说:“和那个一模一样的。”
从老板的角度来讲,他采用的就是,Prototype模式,即原型模式。否则,他需要再花费一些时间和工程师一点一点的探讨关于大楼的一些设计问题。
所谓的原型模式,就是用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
JAVA的Object.clone()就是Prototype模式的应用了。
初看Prototype模式 感觉好像没什么用
我直接new一个对象, 把对象相关属性赋值进去不就可以吗?
这里有几个问题
1. 如果有10个地方需要新对象, 那是不是有10个地方有new, 有10个地方有赋值?
2. 一般属性都是私有的, 你怎么赋值?
3. 一个对象的属性可能是运行时产生的, 如果赋值在对象的内部, 感觉封装性会好一些.
角色
Client类(1个):该类中含有一个原型对象, 当调用其Operation方法时, 它就会调用该原型对象拷贝新的对象出来.
Prototype类:抽象类, 定义拷贝接口, 需要自我拷贝的类要继承该类, 并实现其Clone接口..
各种Prototype类的子类(多个):具体能实现自我拷贝的子类.
使用
飞机工厂已经可以生产直升飞机和超音速飞机, 由于有拷贝技术, 所以, 飞机工厂先生产了一架直升飞机和超音速飞机, 当有客户请求要飞机时, 直接在原型飞机中拷贝一份出来, 给用户.就这么简单, 不需要组装, 调试, 试飞. 效率太高了..
说明:
代码:
…
// 构建原型对象
CHolicopter* pHolicotper = new CHolicopter;
pHolicotper->SetEngineType(3);
CSoundPlane* pSoundPlane = new CSoundPlane;
pSoundPlane->SetSpeed(1000);
// 保存原型对象
CPlaneFactory* pPlaneFactory = new CPlaneFactory(pHolicotper, pSoundPlane);
// 现在我需要一架直升飞机(但我可以不需要知道直升飞机类)
CPlane* pPlane = 0;
pPlane = pPlaneFactory->GetHolicopter();
if(pPlane)
{
pPlane->Fly();
delete pPlane;
pPlane = 0;
}
pPlane = pPlaneFactory->GetSoundPlane();
if(pPlane)
{
pPlane->Fly();
delete pPlane;
pPlane = 0;
}
delete pPlaneFactory;
delete pHolicotper;
delete pSoundPlane;
return 0;
看工程005Prototype.rar
http://download.csdn.net/source/2841063
总结:
开始也说过了,
我直接new一个对象, 把对象相关属性赋值进去不就可以吗?
这里有几个问题
1. 如果有10个地方需要新对象, 那是不是有10个地方有new, 有10个地方有赋值?
2. 一般属性都是私有的, 你怎么赋值?
3. 一个对象的属性可能是运行时产生的, 如果赋值在对象的内部, 感觉封装性会好一些.
其实对象的创建集中起来, 始终比分散的好.
Prototype模式就是: 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
适用性
1. 当要实例化的类是在运行时刻指定时,例如,通过动态装载.
2. 为了避免创建一个与产品类层次平行的工厂类层次时;
3. 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。
当创建给定类的实例的过程很昂贵或很复杂时,就使用原型模式。 例如对象的创建流程很复杂(Builder模式), 那你可以使用Builder模式对原型对象进行创建, 那以后的对象的创建通过Prototype模式来创建.
又例如反序列化, IO操作如此频繁, 一次就够了, 如果需要, 后面的对象就Clone出来就可以了.
客户的代码在不知道要实例化何种特定类的情况下,也可以制造出新的实例(必须保证已经存在一个对象实例)。
你有一个细胞, 你想要该细胞的一个拷贝, 那你自己用分子, 原子等自己去按照该细胞的属性做一个.
还是让该细胞分裂一个? 答案就不用说了.
如果一个对象的创建通过复杂的流程创建(创建后使用属性保存), 那我使用Clone的方法是不是好一些, 当然了.
Prototype模式并不是简简单单一个clone方法,Prototype模式的意义在于动态抽取当前对象运行时的状态,同时通过提供统一的clone接口方法,使得客户代码可以在不知道对象具体类型时仍然可以实现对象的拷贝,而无需运用type-switch检测对象的类型信息来分别调用创建方法来创建一个新的拷贝。
使用Prototype模式,在需要复制自身来创建新产品,不需要对象的实际类型而致需要知道抽象基类即可,但是必须保证已经存在一个对象实例。
项目应用
在一个C/S模式的系统中, 服务端需要定时对客户端的状态进行查询, 所以我在客户端就定义了一个状态类, 创建一个状态对象, 在服务端请求客户端状态时, 客户端就拷贝一份状态出来, 做了相关处理后发送给服务端.
服务端想控制客户端, 也生成一个状态对像, 然后发给客户端.
引用:
http://blog.csdn.net/chollima/archive/2010/06/19/5680663.aspx
http://www.java3z.com/cwbwebhome/article/article2/21186.html
http://blog.sina.com.cn/s/blog_48db23f6010006zp.html