23种设计模式 - 行为型
Template模式
UML图:
解决的问题:
应用程序中某些问题的解决办法或算法具有相同的结构顺序即逻辑框架,可以将逻辑(算法)框架封装在父类中,在各个子类中提供算法步骤的不同实现。
原理:
基类中TemplateMethod()即为逻辑算法的框架,在TemplateMethod中调用Primitive1()和Primitive2()接口(纯虚函数)。而在各个子类中为Primitive1()和Primitive2()提供不同的实现,从而通过实例化不同的子类得到TemplateMethod()的不同实现。注意:Strategy模式解决的是和Template 模式相同的问题,但Strategy模式将逻辑(算法)封装到一个类中,并采取组合(委托)的方式解决问题。
Template模式是对面向对象依赖倒置原则的一个实例,在基类中定义了子类的实现接口,这样上层(基类)将不依赖于下层(子类),下层将依赖于上层提供的接口来完成实现。然而,Template模式由于在基类中完成了算法的逻辑结构,对于代码的复用和添加是十分不方便的(甚至不可能复用),这也是继承相比委托的最大缺陷。
Strategy模式
UML:
解决的问题:
Strategy解决和模板方法相同的问题,都是将业务逻辑(算法)和具体实现解耦。Strategy模式采用的是组合委托方式。
原理:
Strategy通过将业务逻辑封装在一个类(Context)中,并对该业务逻辑提供一个DoAction()方法。在DoAction()方法中封装了具体的业务逻辑步骤,这些业务逻辑步骤是通过成员对象中组合的Strategy对象代理完成的。Strategy提供算法逻辑的抽象接口,它的各个子类提供接口逻辑的不同实现。
State模式
UML图:
解决的问题:
很多系统或者应用程序都设计到复杂的状态变化,例如有限状态机、开关门控制。当系统中状态数目不是很多是,switch/case语句可以处理,但当状态数目增多时,switch/case语句将变得很难维护并容易出现问题。并且状态逻辑和动作没有分离,使系统的扩展性和维护性很难保证。而State模式完成了动作和状态的分离,将每一个分支都封装到独立的类中。
原理:
State模式相比较而言是一个比较复杂的模式。首先需要在Context中组合state成员对象,并定义用于执行当前操作的OperationInterface()抽象接口,和操作执行后控制Context状态变化的ChangeState()的默认实现(设置成员变量state的值)。并将OperationInterface()的实现委托给抽象基类State。抽象基类State中声明了OperationInterface()和ChangeState()抽象接口,它的每一个子类代表State模式中的一种状态,在每一个子类中完成当前状态的动作和下一个状态的转换。注意,实现时定义State为Context的友员类,从而授权State的子类访问Context的ChangeState()方法。
Observer模式
UML图:
解决的问题:
建立一个一对多的依赖关系,当“一”变化时,“多”能够依赖变化得到通知并同步改变。举例而言,当对一组数据进行统计分析时,统计的结果通过多种样式(网页表格,柱状,饼状)进行显示,当数据发生变化时,我们希望所有这些显示得到同步的通知。该问题即可通过Observer模式解决。
原理:
被观察对象Subject提供添加Attach()和删除Detach()方法,这两个方法完成Observer对象的注册和删除,并提供关键的Notify方法,该方法将遍历调用所有已注册Observer对象的Update()方法,从而使各个已注册Observer对象得到通知。为保存各个已注册对象,Subject对象中需要list/vector型Observers数据成员。而为注册、注销和保存当前Subject状态,Observer对象中应保存Subject数据成员。
Memento模式
UML图:
解决的问题:
在不破坏类的封装性的前提下,捕获并保存一个类的内部状态,这样可以根据保存的状态实施恢复操作
原理:
Originator对象中保存用于恢复状态的Memento数据成员,需要保存状态时调用CreateMemento(),需要恢复状态时,调用RestoreToMemento方法。
Mediator模式
UML图:
解决的问题:
解决对象之间的通信问题。当系统中对象逐渐增多,对象间的通信将变得很复杂,我们提供Mediator中介者完成不同对象之间的通信,这样做可以避免对象间通信的显示调用,如:A要调用B的方法,无需再了解B,通过Mediator模式完成!
原理:
中介者Mediator类中包含需要通信的数据成员对象,如:ConcreteColleagueA和ConcreteColleagueB。并定义了这两个对象通信的成员函数DoActionAtoB()和DoActionBtoA(). Colleague中包含中介者Mediator对象数据成员,如需通信,调用Action()方法,Action方法将通过Mediator代理AtoB Or BtoA的通信。
Command模式
UML图:
解决的问题:
将命令的请求与具体执行分离开,封装到不同的类中。从而实现调用操作的对象和操作对象具体实现的类之间的解耦。
原理:
Command对象作为操作的调用和执行中间的“代理”。Invoker中包含Command对象数据成员,Command对象中包含Receiver数据成员。当Invoker调用Execute时,命令代理给Receiver的Action方法.
Visitor模式
UML图:
解决的问题:
!!!需更新!!!
原理:
Element中包含Accept方法根据当前Visitor参数调用其VisitConcret(Element *)方法,而在VisitConcret(Element *)方法中调用参数的Element*的Changing()操作完成具体更改。
Chain of Responsibility模式
UML图:
解决的问题:
程序中经常需要处理一个消息,我们预先定义好了某消息的处理链,但我们并不关注到底是链上哪一个对象完成了消息的处理。消息在链上传递,直到消息被处理。类似问题可以通过该模式解决。
原理:
Handle对象中包含有Handle数据成员,并定义了HandleRequest()方法,该方法首先检测自己是否可以处理消息,如果自己能处理,则处理并直接返回。如果不能处理,则通过GetHandle()获取当前Handle数据成员,将当前消息传递给下一个Handle进行处理。
Iterator模式
UML图:
解决的问题:
解决聚合对象的遍历问题,类似于STL的iterator。
原理:
聚合对象Aggregate本身定义了操作其聚合成员的方法,CreateIterator()返回一个Aggregate对象的迭代器。Iterator在初始化时赋值起Aggregate数据成员,并对外提供操作聚合对象的方法,方法的实现通过调用数据成员Aggregate的具体方法实现。
Interpreter模式
UML图:
解决的问题:
一些应用内建了自己的脚本和应用语言来定义用户的操作,解释器模式目的是使用一个解释器为用户提供语言的解释功能。 (需更新!!!)
原理:
Context类中提供解释器的全局信息。TerminalExpression和NonterminalExpression根据自身完成的功能提供解释器的不同实现。