文档库 最新最全的文档下载
当前位置:文档库 › 常见设计模式的解析

常见设计模式的解析

常见设计模式的解析

常见设计模式的解析之一-Factory模式

作用:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。

UML结构图:

抽象基类:

1)Product:创建出来的对象的抽象基类.

2)Factory:创建对象的工厂方法的抽象基类.

接口函数:

1)Creator::FactoryMethod:纯虚函数,由派生类实现,创建出对应的Product.解析:

在这个模式中,有两个抽象基类,一个是Product为创建出来的对象的抽象基类,一个是Factory是工厂的抽象基类,在互相协作的时候都是由相应的Factory派生类来生成Product的派生类,也就是说如果要新增一种Product那么也要对应的新增一个Factory,创建的过程委托给了这个Factory.也就是说一个Factory 和一个Product是一一对应的关系.

常见设计模式的解析之二-Abstract Factory模式

作用:

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。UML结构图:

抽象基类:

1)ProductA,ProductB:分别代表不同类型的产品,而它们的派生类则是这种产品的一个实现.

2)AbstractFactory:生产这一系列产品的一个抽象工厂,它的派生类是不同的实现.

接口函数:

1)AbstractFactory::CreateProductA和AbstractFactory::CreateProduc tB:分别是生产不同产品的不同的实现,由各个派生出来的抽象工厂实现之.

解析:

Abstract Factory模式和Factory最大的差别就是抽象工厂创建的是一系列相关的对象,其中创建的实现其实采用的就是Factory模式的方法,对于某个实现

的有一个派生出来的抽象工厂,另一个实现有另一个派生出来的工厂,等等.

可以举一个简单的例子来解释这个模式:比如,同样是鸡腿(ProductA)和汉堡(P roductB),它们都可以有商店出售(AbstractFactory),但是有不同的实现,有肯德基(ConcreateFactory1)和麦当劳(ConcreateFactory2)两家生产出来的不同风味的鸡腿和汉堡(也就是ProductA 和ProductB的不同实现).

而负责生产汉堡和鸡腿的就是之前提过的Factory模式了.

抽象工厂需要特别注意的地方就是区分不同类型的产品和这些产品的不同实现. 显而易见的,如果有n种产品同

常见设计模式的解析之三-Builder模式

作用:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。UML结构图:

适用于以下情况:

1)当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。

2)当构造过程必须允许被构造的对象有不同的表示时。

抽象基类:

1)Builder:这个基类是全部创建对象过程的抽象,提供构建不同组成部分的接口函数

接口:

1)Builder::BuildPartA,Builder::BuildPartB:是对一个对象不同部分的构建函数接口,Builder的派生类来具体实现.

另外还有一个需要注意的函数,就是Director::Construct函数,这个函数里面

通过调用上面的两个接口函数完成对象的构建--也就是说各个不同部分装配的

过程都是一致的(同样的调用的Construct函数),但是不同的构建方式会有不同的表示(根据Builder的实际类型来决定如何构建,也就是多态)

解析:

Builder模式是基于这样的一个情况:一个对象可能有不同的组成部分,这几个部分的不同的创建对象会有不同的表示,但是各个部分之间装配的方式是一致的. 比方说一辆单车,都是由车轮车座等等的构成的(一个对象不同的组成部分),不

同的品牌生产出来的也不一样(不同的构建方式).虽然不同的品牌构建出来的单车不同,但是构建的过程还是一样的(哦,你见过车轮长在车座上的么?).

也就是说,Director::Construct函数中固定了各个组成部分的装配方式,而具体是装配怎样的组成部分由Builder的派生类实现.

实现:

Builder模式的实现基于以下几个面向对象的设计原则:1)把变化的部分提取出来形成一个基类和对应的接口函数,在这里不会变化的是都会创建PartA 和Par tB,变化的则是不同的创建方法,于是就抽取出这里的Builder基类和BuildPart A,BuildPartB接口函数 2)采用聚合的方式聚合了会发生变化的基类,就是这里Director聚合了Builder类的指针.

常见设计模式的解析之四-Prototype模式

作用:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。UML结构图:

抽象基类:

1)Prototype:虚拟基类,所有原型的基类,提供Clone接口函数

接口函数:

1)Prototype::Clone函数:纯虚函数,根据不同的派生类来实例化创建对象.

解析:

Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性,但是通过不同派生类实现的Clone接口函数可以完成与"虚

拟构造函数"同样的效果.举一个例子来解释这个模式的作用,假设有一家店铺是配钥匙的,他对外提供配制钥匙的服务(提供Clone接口函数),你需要配什么钥

匙它不知道只是提供这种服务,具体需要配什么钥匙只有到了真正看到钥匙的原型才能配好.也就是说,需要一个提供这个服务的对象,同时还需要一个原型(Prot otype),不然不知道该配什么样的钥匙.

常见设计模式的解析之五-Singleton模式

作用:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

UML结构图:

解析:

Singleton模式其实是对全局静态变量的一个取代策略,上面提到的Singleton 模式的两个作用在C++中是通过如下的机制实现的:1)仅有一个实例,提供一个类的静态成员变量,大家知道类的静态成员变量对于一个类的所有对象而言是惟一的2)提供一个访问它的全局访问点,也就是提供对应的访问这个静态成员变

量的静态成员函数,对类的所有对象而言也是惟一的.在C++中,可以直接使用类域进行访问而不必初始化一个类的对象.

下面的实现其实是Singleton的一个简单实现,并不是特别的通用,一般的,如果

一个项目中需要使用到Singleton模式比较多的话,那么一般会实现一个Singl eton的模板类,模板类的模板参数是需要采用Singleton模式的类。

常见设计模式的解析之六-Adapt模式

作用:

将一个类的接口转换成客户希望的另外一个接口。Adapt 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

UML示意图

1)采用继承原有接口类的方式

2)采用组合原有接口类的方式

解析:

Adapt模式其实就是把完成同样的一个功能但是接口不能兼容的类桥接在一起使之可以在一起工作,这个模式使得复用旧的接口成为可能.

Adapt模式有两种实现办法,一种是采用继承原有接口类的方法,一种是采用组合原有接口类的方法。

常见设计模式的解析之七-Bridge模式

作用:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

UML结构图:

1)Abstraction:某个抽象类,它的实现方式由Implementor完成.

2)Implementor:实现类的抽象基类,定义了实现Abastraction的基本操作,而它的派生类实现这些接口.

接口函数:

1)Implementor::OperationImpl:定义了为实现Abstraction需要的基本操作,由Implementor的派生类实现之,而在Abstraction::Operation函数中根据不同的指针多态调用这个函数.

解析:

Bridge用于将表示和实现解耦,两者可以独立的变化.在Abstraction类中维护一个Implementor类指针,需要采用不同的实现方式的时候只需要传入不同的Implementor派生类就可以了.

Bridge的实现方式其实和Builde十分的相近,可以这么说:本质上是一样的,只是封装的东西不一样罢了.两者的实现都有如下的共同点:抽象出来一个基类,这个基类里面定义了共有的一些行为,形成接口函数(对接口编程而不是对实现编程),这个接口函数在Buildier中是BuildePart函数在Bridge中是Operation Impl 函数;其次,聚合一个基类的指针,如Builder模式中Director类聚合了一个Builder基类的指针,而Brige模式中Abstraction类聚合了一个Impleme ntor基类的指针(优先采用聚合而不是继承);而在使用的时候,都把对这个类的使用封装在一个函数中,在Bridge中是封装在Director::Construct函数中,因为装配不同部分的过程是一致的,而在Bridge模式中则是封装在Abstraction:: Operation函数中,在这个函数中调用对应的Implementor::OperationImpl 函数.就两个模式而言,Builder封装了不同的生成组成部分的方式,而Bridge封装了不同的实现方式.

因此,如果以一些最基本的面向对象的设计原则来分析这些模式的实现的话,还是可以看到很多共同的地方的.

常见设计模式的解析之八-Composite模式

作用:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

UML结构图:

1)Component:为组合中的对象声明接口,声明了类共有接口的缺省行为(如这里的Add,Remove,GetChild函数),声明一个接口函数可以访问Component的子组件.

接口函数:

1)Component::Operatation:定义了各个组件共有的行为接口,由各个组件的具体实现.

2)Component::Add添加一个子组件

3)Component::Remove::删除一个子组件.

4)Component::GetChild:获得子组件的指针.

解析:

Component模式是为解决组件之间的递归组合提供了解决的办法,它主要分为两个派生类,其中的Leaf是叶子结点,也就是不含有子组件的结点,而Composite 是含有子组件的类.举一个例子来说明这个模式,在UI的设计中,最基本的控件是诸如Button,Edit这样的控件,相当于是这里的Leaf组件,而比较复杂的控件比如List则可也看做是由这些基本的组件组合起来的控件,相当于这里的Composite,它们之间有一些行为含义是相同的,比如在控件上作一个点击,移动操作等等的,这些都可以定义为抽象基类中的接口虚函数,由各个派生类去实现之,这些都会

有的行为就是这里的Operation函数,而添加,删除等进行组件组合的操作只有

非叶子结点才可能有,所以虚拟基类中只是提供接口而且默认的实现是什么都不做.

常见设计模式的解析之九-Decorator模式

作用:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator 模式相比生成子类更为灵活。

UML结构图:

抽象基类:

1)Component:定义一个对象接口,可以为这个接口动态的添加职责.

2)Decorator:维持一个指向Component的指针,并且有一个和Component

一致的接口函数.

接口函数:

1)Component::Operation:这个接口函数由Component声明,因此Compon ent的派生类都需要实现,可以在这个接口函数的基础上给它动态添加职责.

解析:

Decorator的派生类可以为ConcreateComponent类的对象动态的添加职责,或者可以这么说:Decorator的派生类装饰ConcreateComponent类的对象.具体是这么实现的,首先初始化一个ConcreateComponent类的对象(被装饰者),采用这个对象去生成一个Decorator对象(装饰者),之后对Operation函数的调用则是对这个Decorator对象成员函数的多态调用.这里的实现要点是Decora tor类和ConcreateComponent类都继承自Component,从而两者的接口函数是一致的;其次,Decorator维护了一个指向Component的指针,从而可以实现对Component::Operation函数的动态调用.

常见设计模式的解析之十-Proxy模式

作用:

为其他对象提供一种代理以控制对这个对象的访问。

UML结构图:

抽象基类:

1)Subject:定义了Proxy和RealSubject的公有接口,这样就可以在任何需要

使用到RealSubject的地方都使用Proxy.

解析:

Proxy其实是基于这样一种时常使用到的技术-某个对象直到它真正被使用到的时候才被初始化,在没有使用到的时候就暂时用Proxy作一个占位符.这个模式

实现的要点就是Proxy和RealSubject都继承自Subject,这样保证了两个的

接口都是一致的.

常见设计模式的解析之十一-TemplateMethod模式

作用:

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMetho d 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。UML结构图:

抽象基类:

1)AbstractClass:抽象基类,定义算法的轮廓

解析:

TemplateMethod 的关键在于在基类中定义了一个算法的轮廓,但是算法每一步具体的实现留给了派生类.但是这样也会造成设计的灵活性不高的缺点,因为

轮廓已经定下来了要想改变就比较难了,这也是为什么优先采用聚合而不是继承的原因.

常见设计模式的解析之十二-ChainOfResponsibility 模式

作用:

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止. UML结构图:

抽象基类:

1)Handler:定义一个处理请求的接口,在图中这个接口就是HandleRequset函数,这个类同时有一个指向Handler对象的指针,指向后续的处理请求的对象(如果有的话).

解析:

这个模式把可以处理一个请求的对象以链的形式连在了一起,让这些对象都有处理请求的机会.好比原来看古装电视中经常看到皇宫中召见某人的时候,太监们(可以处理一个请求的对象)就会依次的喊:传XX...这样一直下去直到找到这个

人为止.ChainOfResponsibility模式也是这样的处理请求的,如果有后续的对象可以处理,那么传给后续的对象处理,否则就自己处理请求.这样的设计把请求的发送者和请求这种的处理者解耦了,好比发号的皇帝不知道到底是哪个太监最后会找到他要找到的人一般,只管发出命令就OK了.

相关文档