设计模式在LWGUI的研究实现.docx_第1页
设计模式在LWGUI的研究实现.docx_第2页
设计模式在LWGUI的研究实现.docx_第3页
设计模式在LWGUI的研究实现.docx_第4页
设计模式在LWGUI的研究实现.docx_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

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

文档简介

设计模式课程论文题 目: 设计模式在LWGUI的实现研究 姓 名: 学 号: 专 业: 班 级: 导 师: 摘要:设计模式的主要作用是适应变化的需求,其灵活性可以使设计方案更容易扩展和复用。在系统设计中,应尽量使用成熟的设计模式来优化设计模型的局部设计。本文以一个轻量级的跨平台的图形用户界面的框架系统(Light Weight GUI,LWGUI)为例,详细介绍了观察者模式和外观模式这两种模式在LWGUI系统中的应用实现。关键词:设计模式;扩展;复用;观察者模式;外观模式1引 言软件复用是软件开发人员的不懈追求,它能够提高软件生产率以及软件质量。针对软件复用,我们采用设计模式来记录软件设计知识,这可以使软件复用从代码复用提高到软件开发各阶段知识的复用。设计模式是可复用面向对象软件的基础,它以系统化和规格化的方式记录了可重复使用的软件设计方案和经验。它区分、命名并且抽象了面向对象设计中的通用概念。设计模式通过明确对象、对象间的协作和职责分配,捕捉到了隐藏在设计背后的意图。2设计模式2.1观察者模式 (1) 设计意图 观察者模式的设计意图包括: 1) 定义对象之间多对一的依赖关系,也即多个对象依赖于一个对象的关系,同时保证,当被依赖的对象状态发生变化时,所有的依赖者会被自动地通知。观察者模式的另一个名称“出版订阅模式”很好地说明了这个设计意图:被依赖的对象向外发布自己的状态,而此前订阅了该状态的所有对象都会得到通知,这其实类似于一种消息在对象间的广播。 2) 当一个对象需要通知另外一个对象,而又无法预知哪些对象将被通知,通过观察者模式就可以减弱通知对象和被通知对象之间的耦合关系。 3) 当一个模块(模块A)的变化需要另一个模块(模块B)做出相应的修改,而又不知道有多少个类会被修改时,使用观察者模式就可以切断这种依赖关系,即模块A的变化不再影响模块B,模块B也无需做任何修改。换句话说,这时,模块B对模块A的依赖关系由直接依赖转变为间接依赖,具体的依赖关系是由模块A动态设定的。因此,两个模块可以在互不干扰的情况系下,相对独立地被复用和修改。 (2) 基本结构 图2-1为观察者模式的结构图。在结构图中,有如下一些类,它们共同完成观察者模式的各项职责。 1) 主体(Subject)类:即被观察者类的基类,它管理所有的观察者,并提供添加和删除观察者的方法,观察者的数量一般不受限制。 2) 观察者(Observer)类:定义一个通知接口来接受主体类发来的通知消息。 3) 具体的主体(ConcreateSubject)类:即具体的被观察者类,它针对不同的需求,实现具体的主体属性和方法,决定何时发送通知消息等。 4) 具体的观察者(ConcreateObserver)类:针对不同的需求,实现具体的通知接口,以接收具体的主体类发来的通知消息,并可以根据需要对消息进行特定的处理。 图2-1观察者模式结构图2.2外观模式 (1) 设计意图 外观模式可以为一个子系统中的多个类提供统一的接口。外观模式定义了一个高层次的接口,并使一个子系统更易于使用。 (2) 基本结构 图2-2 为外观模式的结构图。 图2-2 外观模式结构图 图2-2中,子系统的接口不一定是具体的外观类,它和外观类之间的关系可能会有两种: 1) 子系统的接口是一个抽象类,不包含任何属性和具体实现,其中定义的所有的接口函数都是纯虚函数;而外观类是该抽象类的派生类,隐藏在子系统中。在这种实现方式中,客户程序所看到的只是一个纯粹的接口,而具体的实现都被外观类封装到了子系统内部。 2) 子系统的接口就是外观类的头文件(对 C+语言而言),客户程序可能会看到一些外观类的私有属性和私有方法。 显然,第一种方法比较纯粹,比较理论,而且,在第一种方法里,如果子系统的接口可以被多个子系统共用,它就会有多个不同的派生类,这在某些情况下非常有用。如果子系统的接口只有一个派生类,即该子系统的外观类,可以使用第二种方法,因为它比较简单和直接。 外观类一般应以单件类(Singleton)的形式出现,这样,客户程序就可以通过单件类的静态方法获得子系统的惟一接口实例。另外,外观类一般要负责创建和销毁子系统中的其它相关对象,管理其它对象的生命周期。当客户程序调用外观类中的接口函数时,外观类必须知道每一个特定的请求应该发送给子系统中的哪个类或对象,或者,应该让子系统中哪些类共同处理。 3观察者模式在LWGUI系统中的应用实现 根据对 LWGUI 系统的架构分析可知,在框架层和操作系统适配器层中,有几个类和消息传递相关,即操作系统适配器会在适当的时候,发送消息给应用程序、屏幕、定时器管理器这三个类。但随着系统不但的扩展,消息的接收者数量,处理方式等都有可能在未来发生变化。在没有引入观察者模式前,系统的结构图如图 3-1 所示。 图3-1 未引入观察者模式时的消息传递方案 LWG_OSAdaptor的派生类负责各具体操作系统的程序启动、主窗口创建、消息接收等工作。程序启动后,对于VxWork等操作系统,该派生类可以通过一个循环不断查询各种操作系统消息(如键盘、鼠标、时钟、网络、串口等消息),对于Windows或Linux等操作系统,可以在相应的派生类中实现一个窗口函数,以接受各种系统消息。 当操作系统适配器类接收到系统消息后,它需要根据系统消息的类型,把消息发送给不同的对象,例如,键盘、鼠标消息发送给屏幕类的对象实例,启动消息发送给应用程序类的对象实例,时钟消息发送给定时器管理器类的对象实例等等。显然,此处的每一个消息都只是发给一个对象,并不会发送给多个观察者,不存在一对多的依赖关系。 但随着消息类型的不断增多,接受消息的控制类在未来也可能会发生变化,而这种变化正好是观察者模式试图解决的问题。而且,操作系统适配器层要移植到不同的操作系统上,实际上存在多个不同的操作系统适配器层实例,所以,框架层的变化应尽可能少地影响操作系统适配器层,否则,系统的扩展性和复用性就无从谈起,这同样符合观察者模式的设计意图。因此,尽管这里不存在一对多的依赖关系,但为了达到减少层与层之间的耦合、把直接依赖变成间接依赖的目的,观察者模式仍可发挥很大的作用。只是在具体实现上,LWGUI中的观察者模式和标准的GoF的观察者模式略有不同。 观察者模式的实现方法如下:在LWGUI中,首先实现了一个Observer类,该类是一个抽象类,其中的 OSMessage()接口可用于接收操作系统消息,相当于观察者模式中的Update()方法。由于该类会同时被框架层和操作系统适配器层使用,应把它放在独立的应用包中。Observer类的代码如下所示。 class LWG_OSMsgObserver public: virtual LWG_OSMsgObserver() virtual void OSMessage(LWG_Message * pMsg) = 0; ; 框架层的屏幕、应用程序、定时器管理器等类都是从LWG_OSMsgObserver 类中继承出来的,这样它们都具有接收操作系统消息的能力。负责转发操作系统消息的类是操作系统适配器层的适配器类LWG_OSAdaptor,但是,由于每种特定类型的消息不是发送给所有的观察者,而是发送给某一个注册了该类型消息的接收者,因此,记录观察者的方式和标准的观察者模式略有不同。 先定义消息类型的枚举结构: enum LWG_MSG_TYPE LWG_MSG_STARTUP, /系统启动消息 LWG_MSG_HALT, /系统停止消息 LWG_MSG_DRAW, /屏幕刷新或窗口元素重画消息 LWG_MSG_KEY, /键盘消息 LWG_MSG_MOUSE, /鼠标消息 LWG_MSG_TIMER, /定时器消息 /以上为所有的系统消息 /系统内部使用,不是一个消息类型,表示最大的系统消息个数, /之前为所有的系统消息,之后为内部消息 LWG_MAX_SYS_MSG, /请求重画消息,控件需要重画时向窗口发送此消息,/窗口需要重画时向屏幕发送此消息,/由屏幕根据该窗口是否是焦点窗口来决定如何重画LWG_MSG_DRAW_REQUEST,LWG_MSG_FOCUS, /焦点切换消息LWG_MSG_NOTIFY, /通知消息LWG_MSG_UPDATE_VIEW / MVC模式的视图更新消息;对于每一类系统消息,需要记录一个接收该消息的观察者,而且,在 LWGUI 系统中,每一类消息只能有一个观察者(当然,同一个观察者可以观察多个类消息),因此,只需在LWG_OSAdaptor类中定义一个大小为LWG_MAX_SYS_MSG 的数组,用该数组来保存每个消息类型对应的观察者对象指针即可。观察者注册时,需要提供它想注册的消息类型,然后该观察者的指针就会被记录在数组的相应位置。当然,注册的前提是该观察者类实现了LWG_OSMsgObserver接口。当LWG_OSAdaptor类接收到系统消息时,只要从数组中查询出该系统消息对应的观察者对象指针,然后调用该指针的OSMessage()方法,就可以把消息发送给观察者来。LWG_OSAdaptor 类和观察者模式的相关代码如下:class LWG_OSAdaptorpublic:/* 注册系统消息的观察者* 每个系统消息只能有一个观察者(即消息接受者,LWG_OSMsgObserver的子类)* type 系统消息类型* pObserver注册的系统消息的观察者指针* 该消息以前设置的观察者指针*/LWG_OSMsgObserver * SetMsgObserver(const WORD type, LWG_OSMsgObserver * constpObserver);/* 发送系统消息给注册的观察者* pMsg 指向要发送的系统消息,由于是同步消息,发送者必须负责分配和释放该消息*/void SendMsg(LWG_Message * pMsg);protected:/ 记录所有的系统消息的观察者的数组 LWG_OSMsgObserver * m_ppObserverLWG_MAX_SYS_MSG; ; LWG_OSMsgObserver * LWG_OSAdaptor:SetMsgObserver(const WORD type, LWG_OSMsgObserver * const pObserver) LWG_OSMsgObserver * tmp = m_ppObservertype; m_ppObservertype = pObserver; return tmp; void LWG_OSAdaptor:SendMsg(LWG_Message * pMsg) if(pMsg-wTypewType) m_ppObserverpMsg-wType-OSMessage(pMsg); 最终的框架层和操作系统适配器层之间的关系如图 3-2 所示。 图3-2 引入观察者模式后的消息传递方案 4外观模式在LWGUI中的应用实现 LWGUI的适配器子系统很简单,只包含两个分析类。其中,LWG_OSAdaptor 类负责LWGUI系统的启动和操作系统消息的转发,LWG_OSDrawInterface类负责将绘图调用转发给特定操作系统中的绘图接口。 由于LWGUI需要移植到不同的操作系统,如果把操作系统相关的代码实现在LWG_OSAdaptor类和LWG_OSDrawInterface类中,则必须为每个操作系统准备一个适配器类和绘图接口类。编译的时候,只需把相应操作系统的适配器类和绘图接口类连接到框架系统即可。这种方法虽然可行,但存在一些问题,例如,为了保证代码的一致性,不同操作系统的相关代码必须拥有相同的文件名和类名,编码时只能将它们放在不同的目录中,这种做法显然会给以后的管理和维护带来很大的麻烦。 适应不同需求,同时支持多种环境,是GoF设计模式的强项。对于上面提到的适应不同操作系统的问题,需把LWG_OSAdaptor、LWG_OSDrawInterface 类实现为抽象类,即二者看作纯粹的接口,然后,对每种具体的操作系统,都从LWG_OSAdaptor类和LWG_OSDrawInterface类中继承出特定的派生类,将只与具体操作系统的属性和方法实现在派生类中即可。 在Windows系统可生成LWG_Win32Adaptor和LWG_Win32DrawInterface 这两个派生类。在Unix、Linux等支持X11图形环境的系统中,可以生成 LWG_X11Adaptor和LWG_X11DrawInterface这两个派生类。 外观模式的实现方法如下:由上面可知,对于一个具体的操作系统平台,LWGUI适配器子系统只需四个类(两个抽象类和两个派生类)就可以实现所有功能了。为了让这个子系统有一个外部类可见的、统一的接口,是否有必要再添加一个外观类呢? 如果添加一个外观类,则它的职责就是把框架层对适配器子系统的调用请求发送给具体的操作系统适配器类或具体的绘图接口类,然后再由后者进一步将调用转发给操作系统或底层绘图接口。这个外观类的职责并不很多,完全可以合并到其他类中。因此,可以由适配器类LWG_OSAdaptor来承担外观类的职责,而 LWG_OSAdaptor类的头文件可以作为整个适配器子系统的接口直接输出。框架层的客户程序通过LWG_OSAdaptor类来访问整个适配器子系统的功能。一般而言,LWG_OSAdaptor类必须是一个单件类,客户程序可以通过单件类的静态方法来访问外观类的各项功能。此外,LWG_OSAdaptor类必须负责创建和删除绘图接口类,并能把相关的调用发给绘图接口类。图4-1 显示了在 Win32 环境下适配器子系统中外观类。图4-1 Win32 环境下适配器子系统的类图 在LWG_OSAdaptor类只能包含一个指向LWG_OSDrawInterface类的指针,而具体创建绘图接口类的任务,则应交给LWG_OSAdaptor类的派生类来完成。下面的代码显示了在Win32系统中,当程序启动时,Win32的适配器类LWG_Win32Adaptor负责创建Win32的绘图接口类LWG_Win32DrawInterface的过程。 bool LWG_Win32Adaptor:InitInstance() if (! m_pDraw) m_pDraw = new LWG_Win32DrawInterface(); 由于LWG_OSAdaptor类是一个外观类,客户程序的所有调用都必须通过它传入子系统,必须在LWG_OSAdaptor类中把绘图接口中的所有绘图函数重新定义一遍。当客户程序调用这些绘图接口时,LWG_OSAdaptor类就可以通过指向 LWG_OSDrawInterface类的指针,直接调用具体的绘图接口

温馨提示

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

评论

0/150

提交评论