GoF几种设计模式举例及其应用.doc_第1页
GoF几种设计模式举例及其应用.doc_第2页
GoF几种设计模式举例及其应用.doc_第3页
GoF几种设计模式举例及其应用.doc_第4页
GoF几种设计模式举例及其应用.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

GoF几种设计模式举例及其应用1090379131 易余GOF即Gang of Four,就Java语言体系来说,GOF的设计模式是Java基础知识和J2EE框架知识之间一座隐性的桥。实际上,GoF的设计模式并不是一种具体技术,它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧,让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,GoF的设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。本文介绍几种常用的设计模式的举例和应用。适配器(Adapter) 如何解决不相容的接口问题,或者如何为具有不同接口的类似构件提供稳定的接口?这样的问题的解决方案就是通过中介适配器对象,将构件的原有接口转换为其他接口。应用举例:POS系统需要支持多种第三方外部服务,其中包括税金计算器,信用卡授权服务,库存系统和账务系统。这些外部服务都具有不同的API,并且无法改变。这样的问题解决方案就是:增加一层间接性对象,通过这些间接对象将不同的外部接口调整为在应用程序内使用的一致接口。如上图所示,对于选定的外部服务,将选用一个特定的适配器实例来表示。例如针对账务系统的SAP,当向外部接口发出postSale请求时,首先通过适配器进行转换,使其能够通过HTTP上的SOAP XML接口来访问在SAP在局域网上提供的Web Service。单实例类(Singleton)工厂设计模式也称为简单工厂,经常描述为抽象工厂的变种。工厂设计模式引发出另一个新的问题,即谁来创建工厂自身和如何访问工厂。代码在不同的位置都需要访问适配器以调用外部服务,所以就需要代码在不同的位置调用工厂中的方法。在这里就存在可见性的问题,即如何获得单个工厂实例的可见性以及单点访问。解决方案:对类定义静态方法返回单实例。其中的关键思想是,对类定义静态方法getInstance,该方法提供了类的唯一实例。例如:public class Registerpublic void Initialize do some work AccountingAdapter=ServicesFactory.getInstance().getAccountingAdapter(); do somework 由于公共类的可见性是全局的,因此代码的任何一点,在类的任何方法中,都可以写为:SingletonClass.getInstance()例如SingletonClass.getInstance().doFoo(),这种写法就是为了获得对于单实例类的实例可见性,并且对其发送消息。单实例类还存在另一个问题,为什么不将所有服务的方法都定义成类自己的静态方法,而是使用有实例方法的实例对象?原因如下:实例方法允许定义单实例类的子类以对其进行精化。静态的方法不是多态的,而且大多数语言中不允许在子类中对其覆写。大多数面向对象的远程通信机制只支持实例方法的远程使用而不支持静态方法。类并非在所有的场景中都是单实例类。在一个应用中是单实例的,而在另一个实例中却可能是多实例的,并且在开始设计的时候考虑使用单实例的不多见。因此使用实例方法的解决方案有更大的灵活性。观察者模式(Observer)观察者模式支持低耦合,它允许现有视图或者表示层使用新的窗口来代替特定的窗口,同时不会对非UI对象产生影响。例如,如果模型对象不知道Java Swing对象,那么久可以拔掉Swing接口或者特定的窗口,然后插入其他的东西。不同类型的观察者关注观察对象的状态变化或事件,并且在观察对象产生事件时以自己独特的方式的做出反应。观察对象与观察者保持低耦合,就使用观察者设计模式。解决方案为:定义观察者接口,观察者实现此接口。对象可以动态关注某事件的观察者,并在事件发生时通知他们。下图描述了此类解决方案。此例的主要思想和步骤是:定义接口。在本例中式具有onPropertyEvent操作的PropertyListener。定义实现该接口的窗口。SaleFrame1实现onPropertyEvent方法。在SaleFrame1窗口初始化时,向其传递Sale实例以显示总额。SaleFrame1窗口通过addPropertyListener消息向Sale实例注册或者订阅特性事件的通知。也就是说总额变化时,该窗口会得到通知。Sale并不知道SaleFrame1对象,它只知道实现了PropertyListener对象。这样就降低了Sale和窗口的耦合。Sale实例就成为了特性事件的发布者,当总额发生变化时,它会遍历所有订阅了的PropertyListener,并且通知每一个订阅者。SaleFrame1就是观察者组合(Composite)商场有不同的定价策略,一般商店在解决冲突策略时会应用“对顾客最有利”的策略来解决冲突。但有时在财政困难时期,商店也会采用最高价格的策略来解决冲突。因此商场存在多个策略,同样定价策略可以与所购买的产品类型相关,那么如何能够像处理非组合对象一样,多态地处理一组对象或者具有组合结构的对象?这里提出的解决方案是:采用组合模式,定义组合和原子对象的类,使他们实现相同的接口。如下图所示。在该设计中,其组合类CompositeBestForCoustomerstrategy继承了属性PricingStrategy,该属性包含一组IsalePricingStrategy对象。组合对象的标志性特征:外部的组合对象包含一组内部对象,外部和内部对象实现相同的接口。因此,我们对Sale对象附加的策略既可以是组合的CompositeBestForCoustomerstrategy对象,又可以是原子的PercentDiscountPricingStrategy对象。Sale不关心其定价策略是组合的还是原子的。策略(strategy)销售的定价策略有多样性,一段时期内对于所有的销售可能会有10%的折扣,后期可能会对超出200元的销售给予10%的折扣,而且还会有其他大的变化。那么如何设计适应灵活变化的相关的算法或政策?解决方案为:在单独的类中分别定义每种算法,使其具有共同的接口。由于定价行为根据策略不同,因此我们需要创建多个SalePricingStrategy类,每个类都具有多态地getTotal方法,每个getTotal方法都将Sale作为参数。这样便能够使定价策略对象在Sale中找到打折之前的价格。策略对象依附于语境对象,本例中,语境对象是Sale。当getTotal消息发送给Sale时,它会把工作委派给它的策略对象。类型为Sale的S被传递给了策略,因此策略对象在将来的协作中对其具有参数可见性。项目实践:mySocketi2DB系统中设计模式的具体应用 开发意图:上游系统组织并下发的数据无法存储至下游数据库系统,需要有一个中间软件系统作为数据传送通道完成该功能。系统特征:系统可以通过TCP socket连接从若干个不同的端口实时接收数据,数据源是其他外部具有网络发送数据功能的系统。将接收的数据存储至现在市面上各主流的数据库系统。1)单一实例类模式系统运行时参数都存储在CGlobalData实例对象中,要求多线程可以读其中的数据,所以这些参数数据只需要一份,所以使用单一实例类。 class CGlobalData private: CGlobalData(); virtual CGlobalData(); static CGlobalData* _instance; public: static CGlobalData* GetInstance(void); static void KillGlobalData(void);2)观察者模式系统运行时信息及错误需要显示在对话框中,定义接口ITrackListener,对话框对象实例实现该接口,并且向发布者CMainProcessorThread登记。当有这样的信息需要显示时,发布者发布该事件。 interface ITrackListener public: virtual void OnTrackEvent(CString sInfo, int clientID, bool bShowPort, int IsError) = 0; ; void CMainProcessorThread:RegisterTrackListener(ITrackListener *listener) this-m_pTrackListeners-push_back(listener); void CMainProcessorThread:PublishTrackEvent(CString sInfo, int clientID, bool bShowPort, int IsError) list:iterator it; for (it=this-m_pTrackListeners-begin(); it!=this-m_pTrackListeners-end(); it+) (*it)-OnTrackEvent(sInfo, clientID, bShowPort, IsError); void CSocketi2DBDlg:OnTrackEvent(CString sInfo, int clientID, bool bShowPort, int IsError) CGlobalData* gData = CGlobalData:GetInstance(); while (!gData-CanAddLog) Sleep(100); gData-CanAddLog = false; this-OutPut2Screen(sInfo, clientID, bShowPort, IsError); gData-CanAddLog = true;总结 从案例中

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论