C++语言与软件重用_第1页
C++语言与软件重用_第2页
C++语言与软件重用_第3页
C++语言与软件重用_第4页
C++语言与软件重用_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

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

文档简介

1、132 可重用的面向对象设计模式可重用的面向对象设计模式设计模式概述设计模式概述1. 面向对象设计的任务:面向对象设计的任务:应用系统设计应用系统设计工具库设计工具库设计框架设计框架设计其中,框架是已形成源代码的可重用软件体系结构。它体现了应用程序的模块组成关系。框架及框架中的各个模块是形形色色各具特色的。设计模式(Design Pattern)描述了软件开发过程中若干重复出现的问题的解决方案,这些方案不是由过程、算法等底层程序构造实体实现,而是由软件系统中类与类之间或不同类的对象之间的共生关系组成。设计模式可以帮助软件设计人员学习、重用前人的经验和成果。设计模式的分类整理最早见于Erich

2、Gamma在德国慕尼黑大学的博士论文。1995年,Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides合著的Design Patterns:Elements of Reusable Object_Oriented Software系统地整理和描述了23个精选的设计模式(goF模式),为设计模式的学习、研究和推广提供了良好的范例。ClassNameFunction1()Function2()DataMenber1DataMenber2类的表示:子类关系:BaseClassSubclass2设计模式的描述符号设计模式的描述符号(1)类和对象的表

3、示 对象及对象链接:aObjectanotherObject(2)连接的表示)连接的表示 例如:由类A创建类B的对象 ClassAClassB对象创建关系:对象创建关系:示例代码:classA:create() return new ClassB;实例引用关系实例引用关系:ClassAClassBrefrenceName(引用名可选)Window:Area()return aRectArea();WindowArea()RectangleArea()widthheightRectangle:Area() return width* height; 引用关系涉及到的两个类的实例之间可以形成一种代

4、理关系,接受请求的对象将操作委托给它的代理者:aRect对象聚合关系:对象聚合关系:objectsClassAClassB如:下图表示类A中聚合了多个类B的对象。聚合关系可以用对象成员实现,但更经常的是将聚合的成员定义为对象成员指针或引用。由于引用关系也是以对象成员指针或引用来实现的,注意从设计意图上区分对象聚合关系和引用关系对理解设计模式是至关重要的。聚合是对象的包容关系,容器和容器中的对象具有相同的生命期。引用关系又称相识关系,是一种较松散的耦合关系。具有引用关系的对象,仅仅是知道被引用者的存在,并不为对方负责, 1抽象工厂(抽象工厂(Abstract Factory)模式)模式抽象工厂定

5、义一个抽象基类,为创建组合对象提供接口。在面向对象系统中,单个对象的创建由构造函数负责。一个组合对象的动态创建可由一个创建函数创建函数一次性完成,以保证被创建的组合对象的完备性。抽象工厂定义的接口称为创建函数或初始化函数。抽象工厂的不同实现类(可称为实现工厂)的对象可以按不同的风格去实现组合对象的具体创建,可以在保证组合对象被完备创建的前提下,简化组合对象的版本替换、升级换代过程。工厂方法(工厂方法(Factory Method)是一些动态创建对象的方法。是在抽象工厂中声明的一组虚函数,它们负责组合对象中成员对象的创建,其实现代码在实现工厂中定义。 抽象工厂模式通常与工厂方法配合使用抽象工厂模

6、式通常与工厂方法配合使用Product1Part11Part12Product2Part21Part22ProductFactoryProductCreate()FactoryMethod1()FactoryMethod2()ConcreatBFactoryMethod1()FactoryMethod2()ConcreatAFactoryMethod1()FactoryMethod2()图13.1 抽象工厂和工厂方法模式结构举例1创建函数:创建函数:一个抽象的产品工厂类ProductFactory定义了由 两 个 零 件 组 成 的 组 件 产 品 的 创 建 函 数Product* Prod

7、uctCreate (); 以及创建零件的工厂方法。抽象的产品工厂的实现工厂ConcreteProduct重定义了创建零件对象的工厂方法。创建函数Product* ProductCreate ()调用工厂方法,一次性创建产品。返回产品指针。2产品类与零件类产品类与零件类产品类Product与零件类Part可以是分别定义的类,产品类以零件类为自己的对象成员。ProductCreate ()创建一个由2个Part1和1个Part2组合而成的Product组合对象。如果将Product定义为抽象基类,且Part1和Part2定义为它的实现类,则可以得到更加复杂的Product组合关系。class P

8、roductFactory /抽象工厂定义Public: Product* ProductCreate ();Virtual Part1*FactoryMethod1();Virtual Part2*FactoryMethod2();/;class ConcreteA: public ProductFactory /实现工厂定义Public: Virtual Part1*FactoryMethod1() return new Part1; ;Virtual Part2*FactoryMethod2() return new Part2; ;/;Product* ProductFactory:

9、ProductCreate () Product* ptr;Part1* p11= FactoryMethod1();Part1* p12= FactoryMethod1();Part1* p21= FactoryMethod2();Ptr=p11;Return ptr;class Product;class Part1;class Part2;3用工厂对象参数化参数化组合对象创建过程:工厂对象即实现工厂的实例对象。修改生产函数ProductCreate()如下:Product* ProductCreate ( ProductFactory* );/创建函数以抽象工厂的指针为形参。 若再定义一

10、个抽象工厂的实现类:class ConcreteB: public ProductFactory然后声明:ConcreteA* FactoryA; ConcretetB* FactoryB;则调用:ProductCreate (FactoryA);ProductCreate (FactoryA );将生产A、B两个不同系列的产品。很容易实现产品系列的更新换代。如:Product和Part分别代表电脑主机和配件,产品更新换代只要定义新的抽象工厂的实现类,并用它来参数化生产函数即可,不必对系统的其它部分作任何改动。class Applicationstatic Application * inst

11、ance;Application ( );public:static int count;Application ( );static Application* init();Application *Application:instance=NULL;int Application:count=0;Application *Application:init() if (count=0) count=count+1; instance = new Application; coutSingle instance has created, OK!endl; return instance; el

12、se coutCant create more than one instance!endl; return NULL; Application:Application()count=count-1;coutThe single instance has released! GetPicture ()test-Add(new Rectangle); aGraphic = aRectangle;if (test = aGraphic- GetPicture ()test-Add(new Rectangle); /此次Add ()操作实际并不执行 为了识别一个组件是基元还是组合,可按以下示例代码,

13、定义一 个 查 询 函 数GetPicture(),对其返回的组合安全地执行Add()和Remove()操作:3共享对象(共享对象(Flyweight)模式)模式:细粒度对象通常因为数量太大而难以用对象进行建模。共享对象模式提供解决这个难题的有效手段。例如:在文档编辑器程序中,文档对象可能是一个递归组合模式对象。若将文档中的字符作为文档组合对象树的叶结点,可以将字符与文档中的图形、表格等嵌入部分的绘制和格式化作统一处理,并且在程序扩展,支持新字符集时不影响其它部分。但是成千上万的字符对象将耗费大量内存,并产生难以接受的运行开销。共享对象模式解决了这一问题,使大量细粒度对象的使用无须付出这些过于

14、昂贵的代价。一个共享对象(flyweight)可以在多个上下文(context)对象中使用。在每个具体的上下文对象中,flyweight作为一个独立的对象出现,在这一点上与非共享对象没有区别。Flyweight的数据成员被看作它的“内部状态”,是只读的。Flyweight的上下文对象为flyweight提供上下文信息,它们被看作flyweight的“外部状态”。用户对象负责在必要的时候将外部状态传递给Flyweight。以文档编辑器应用为例,它为字母表中每一个字母创建一个共享对象(flyweight)。每个flyweight虽然只存储一个字母代码,但它在文档中的位置和排版风格可以由排版算法或格

15、式化命令决定。逻辑上,文档中的字符每次出现都会有一个对象与之对应。物理上,同一字符共享一个flyweight对象,即同一字符每次出现都指向同一实例,该实例位于对象的共享池中。 flyweight 对象池对象池abcdeihgflkjmnopqrvutsyxwzaRowaColumnaRowaRowAmerica4代理(代理(Proxy)模式)模式代理模式的原型可以参考文件缓冲区与磁盘文件的关系。正如只有在需要访问某个磁盘文件时才为它建立缓冲区的道理一样,在面向对象系统中只有在确实需要某个对象时才对它进行创建和初始化。例如,当需要打开一个多媒体文档时,如果一次性打开其中包含的所有对象,往往造成不

16、必要的巨大开销,因为这些对象在文档中并不是同时可见的,没有必要同时创建它们。此时有必要的是在文档中为这些暂时不需要创建的对象设置一个开销极小的代理对象。由它负责在需要时创建由它代理的主体对象。realSubjectRealSubjectRequest()ClientProxyRequest() realSubject- Request();SubjectRequest()(a) 代理模式结构aClientsubjectaProxyrealSubjectaRealSubject(b)运行时刻的对象代理关系图13.5 代理模式的结构和对象间的关系一般来说,在需要利用一个更通用的对象一般来说,在需要

17、利用一个更通用的对象指针来代替较为专门化的对象指针的时候就指针来代替较为专门化的对象指针的时候就应该使用代理模式。比如,除了以上所述的应该使用代理模式。比如,除了以上所述的多媒体对象的代理外,还可以为不同地址空多媒体对象的代理外,还可以为不同地址空间的对象提供本地代理,为需要提供多种访间的对象提供本地代理,为需要提供多种访问权限的对象提供保护代理等等。问权限的对象提供保护代理等等。智能代理是代理模式的高级形式。智能代理是代理模式的高级形式。普通代理通过简单的指针替换实现代理任务,智能代理还可以在访问被代理对象时执行一些附加的操作,如:在第一次引用一个持久对象时,将它装入内存;在访问一个实际对象

18、前,检查它是否被加锁,以防止冲突;对对象进行引用计数管理,当对象不再被引用时自动将它释放。智能代理的一种具体实现方式是重载智能代理的一种具体实现方式是重载C+的指针运算符的指针运算符-。这样就可以在通。这样就可以在通过指针访问被代理对象时,执行一些附过指针访问被代理对象时,执行一些附加的操作。加的操作。与对象行为相关的模式与对象行为相关的模式行为(行为(behavior)是指对象对请求的可预知是指对象对请求的可预知反应。反应。与对象行为相关的模式描述对象之间的通与对象行为相关的模式描述对象之间的通信关系,处理各种在运行时难以跟踪的复杂信关系,处理各种在运行时难以跟踪的复杂控制流,描述一组对象怎

19、样相互协作以完成控制流,描述一组对象怎样相互协作以完成其中任一对象都无法单独完成的任务。其中任一对象都无法单独完成的任务。5职责链(职责链(Chain of Responsibility)模式:)模式:职责链模式建立一些对象间的链接关系,使请求沿着该链传递,直到链上的某一个对象处理它为止。链上的多个对象都有机会接收和处理请求,从而避免请求的发送者和接收者之间的耦合关系。例如图形用户界面中的上下文有关帮助机制,用户可在当前界面以多种方式提交请求,启动帮助。帮助信息窗口以含有进一步帮助的链接信息。这种链接式对象请求处理通常从第一个接收请求的对象开始,或者自己处理该请求,或者转发给链中下一个候选对象

20、。 HandlerRequest()Concreat1Request()Concreat2Request()Clientsuccessor(a) 职责链结构aClientaHandleraConcreatsuccessoraConcreatsuccessor(b) 职责链对象链接图13.6 职责链模式结构及其对象结构实现职责链的代码示例:class Handlerpublic:Handler(Handler* sp): successor(sp)virtual void Request();private: Handler* successor;这是一个事件处理句柄接口,其子类可以定义自己的R

21、equest()实现。基类的缺省实现如下:virtual void Handler:Request() if (successor)successor- Request();这是一个事先设定的固定的链,只要后继存在就会无条件转发。若在Request()中用不同的请求参数来分派请求,可以实现更灵活的链接。void Request(AbstrctRequest* theRequest) switch(theRequest-Getkind() case 1:Request(AbstrctRequest *) theRequest);break;case 2:/default:/break; 6命令(命令(Command)模式)模式命令模式又称事务(Transaction)模式,命令模式用于封装向某个对象的请求。所谓请求,就是应用程序的操作人员通过图形用户界面(GUI)构件如按钮、图标、菜单项等发出的操作命令。命令模式通过在请求调用对象和请求的执行对象之间增加一个Command中间对象,用以消解多对多复杂性。aReceiverClientConcreateCommandExecute()aReceiveAction()stateCommandExecute()ReceiverAction()Trigger Clicked()aCommandExecute()一个触发器(Ttrigger

温馨提示

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

最新文档

评论

0/150

提交评论