职责链
1.概述
你去政府部门求人办事过吗?有时候你会遇到过官员踢球推责,你的问题在我这里能解决就解决,不能解决就推卸给另外个一个部门(对象)。至于到底谁来解决这个问题呢?政府部门就是为了可以避免屁民的请求与官员之间耦合在一起,让多个(部门)对象都有可能接收请求,将这些(部门)对象连接成一条链,并且沿着这条链传递请求,直到有(部门)对象处理它为止。
例子1:js的事件浮升机制
例子2:
2.问题
如果有多个对象都有可能接受请求,如何避免避免请求发送者与接收者耦合在一起呢?
3.解决方案
职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。(Avoid coupling the sender of a request to itsreceiver by giving morethan one objecta chance to handle the request.Chain the receiving objects andpassthe request along the chain until an object handles it. )
1)在职责链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。2)请求在这条链上传递,直到链上的某一个对象处理此请求为止。3)发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
4.适用性
在以下条件下使用Responsibility 链:
• 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定。
• 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
•可动态指定一组对象处理请求。
5.结构
一个典型的对象结构可能如下图所示:
6. 模式的组成
抽象处理者角色(Handler:Approver):定义一个处理请求的接口,和一个后继连接(可选)
具体处理者角色(ConcreteHandler:President):处理它所负责的请求,可以访问后继者,如果可以处理请求则处理,否则将该请求转给他的后继者。
客户类(Client):向一个链上的具体处理者ConcreteHandler对象提交请求。
7. 效果
Responsibility 链有下列优点和缺点( l i a b i l i t i e s ) :
职责链模式的优点:
1 ) 降低耦合度 :该模式使得一个对象无需知道是其他哪一个对象处理其请求。对象仅需知道该请求会被“正确”地处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需知道链的结构。
2) 职责链可简化对象的相互连接 : 结果是,职责链可简化对象的相互连接。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。
3) 增强了给对象指派职责( R e s p o n s i b i l i t y )的灵活性 :当在对象中分派职责时,职责链给你更多的灵活性。你可以通过在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。你可以将这种机制与静态的特例化处理对象的继承机制结合起来使用。
4)增加新的请求处理类很方便
职责链模式的缺点:1) • 不能保证请求一定被接收。既然一个请求没有明确的接收者,那么就不能保证它一定会被处理 —该请求可能一直到链的末端都得不到处理。一个请求也可能因该链没有被正确配置而得不到处理。2) • 系统性能将受到一定影响,而且在进行代码调试时不太方便;可能会造成循环调用。
8. 纯与不纯的职责链模式
纯的职责链模式:一个具体处理者角色处理只能对请求作出两种行为中的一个:一个是自己处理(承担责任),另一个是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又将责任向下传的情况。请求在责任链中必须被处理,不能出现无果而终的结局。反之就是不纯的职责链模式。在一个纯的职责链模式里面,一个请求必须被某一个处理者对象所接收;在一个不纯的职责链模式里面,一个请求可以最终不被任何接收端对象所接收。
9.实现
我们先来看不纯的职责模式:
假如在公司里,
如果你的请假时间小于0.5天,那么只需要向leader打声招呼就OK了。
如果0.5<请假天数<=3天,需要先leader打声招呼,要不然leader不知你跑哪里,然后部门经理直接签字。
如果3<请假天数 天,需要先leader打声招呼,然后到部门经理签字,最好总经经理确认签字,当你看到这情况后你心里是不是已经有了自己的想法了?写一系列的if语句来一条条的判断.但这样的写法虽然可以实现目前的需求,可如果当流程改了呢?我请假超过3天,告诉leader和总经理签字就可以,那你又得一步一步修改程序。如果if语句的条数发生变化的话我们还必须在代码中添加必要的if判断,这对于程序的维护来说是相当麻烦的.如果我们使用职责链模式的话就可以相当简单了.
命令模式
目的:
任何模式的出现,都是为了解决一些特定的场景的耦合问题,以达到对修改封闭,对扩展开放的效果。命令模式也不例外:
命令模式是为了解决命令的请求者和命令的实现者之间的耦合关系。
解决了这种耦合的好处我认为主要有两点:
1.更方便的对命令进行扩展(注意:这不是主要的优势,后面会提到)
2.对多个命令的统一控制(这种控制包括但不限于:队列、撤销/恢复、记录日志等等)
模式解析:
经典的命令模式包括4个角色:
Command:定义命令的统一接口
ConcreteCommand:Command接口的实现者,用来执行具体的命令,某些情况下可以直接用来充当Receiver。
Receiver:命令的实际执行者
Invoker:命令的请求者,是命令模式中最重要的角色。这个角色用来对各个命令进行控制
访问器
访问者模式就是表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
类图和样例:
抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。
具体访问者(ConcreteVisitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象节点(Element)角色:声明一个接受操作,接受一个访问者对象作为一个参量。
具体节点(ConcreteElement)角色:实现了抽象元素所规定的接受操作。
结构对象(ObiectStructure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。
解析器
意图:
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.
适用性:
1、当有一个语言需要解释执行,并且你可以把该语言中的句子表示为一个抽象的语法树时,可使用解释器模式.而当存在以下情况时,该模式的效果最好:
2、该文法简单,对于复杂的文法,文法的类层次变得庞大而无法管理.此时,语法分析程序生成器这样得工具时更好得选择。它们无需构建抽象语法树即可解释表达式,这样可以节省空间而且还可以节省时间;
3、效率不是一个关键的问题,最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先把他们转换成另外一种形式.例如:正则表达式通常被转换成状态机。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍是有用的.
结构图:
Interpreter设计模式中的几种角色:
AbstractExpression:
- 声明一个抽象的Interpret方法,抽象语法树中所有的节点都必须实现该抽象方法。
TerminalExpression:
- 实现和语法中末端符号相关的Interpret方法。
- 在每个句子的末端符号中均需要一个TerminalExpression实例。
NonterminalExpression:
另外一个实现了AbstractExpression 接口的类,用来处理语法树中非末端节点的语法。它含有下一个AbstractExpression(s)的引用,调用它每个子节点的Interpret方法。
Context:
Interpreter方法所需要的信息的容器,该信息对Interpreter而言全局可见。充当几个AbstractExpresssion 实例之间的通讯频道。
PatternClient:
构建或者接收一个抽象语法书的实例。对于一个特定的句子而言,语法树往往由若干个TerminalExpressions 和NonterminalExpression组成。PatterClient在合适的context下,调用Interpret方法。
Interpreter模式的应用场合是interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题”才适合使用Interpreter模式。
使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。
Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,这时候就不应该采用Interpreter模式了。
效率不是一个Interpreter关心的关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。例如:正则表达式通常被转换成状态机。但即使在这种情况下,如果效率不是一个关键问题,转换器仍可用Interpreter模式实现,该模式仍是有用的。