责任链模式和状态模式对比
常用23中设计模式中,有三种模式容易混淆,这三种模式即责任链模式、状态模式以及策略模式。
状态模式与策略模式比较
定义
- 状态模式:通过改变对象的内部状态而改变对象自身的行为,这个对象表现得就好像修改了它的类一样。
- 策略模式:定义一组算法,并将每一个算法封装起来,使得它们可以互换。算法的替换不影响调用算法的客户端;
异同
- 态模式关键是各个状态子类必须知道下一个状态是啥,且要把逻辑判断转移到各个状态子类中, 客户端不需要了解状态迁移的顺序,且状态模式虽然类图还尼玛和策略模式几乎一样, 但是策略目的是针对单一算法的运行时替换,客户端需要事先了解策略,主动去选择合适的策略, 不存在状态的自动迁移!
责任链模式与状态模式
定义:
- 责任链Chain of Responsibility(CoR)——责任链模式,也叫职责链模式或者职责连锁模式,同状态模式一样,也是对象的行为模式之一,该模式构造一系列分别担当不同的职责的类的对象来共同完成一个任务,对象由每一个对象对其下家的引用而连接起来形成一条链,这些类的对象之间像链条一样紧密相连,而客户端发出的请求在这个链上传递,直到链上的某一个对象决定处理此请求,发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任,所以该模式被称作职责链模式。
责任链模式特点是各个职责类(类比状态模式的状态类们)职责单一不彼此依赖,且职责自动转移,但是和状态模式不同的是,责任链模式的责任类不知道自己的下一个需要转移到的职责是哪个,等价于——发出完成某任务请求的客户端并不知道链上的哪一个对象最终处理这个请求,这个组装过程需要交给环境类去完成,所以非常灵活!
比如客户Client要完成一个任务,这个任务包括a,b,c,d四个部分,首先客户Client把任务交给A,A完成a部分之后,把任务交给B,B完成b部分……直到D完成d部分。再看,政府部分的某项工作,县政府先完成自己能处理的部分,不能处理的部分交给省政府,省政府再完成自己职责范围内的部分,不能处理的部分交给中央政府,中央政府最后完成该项工作。还有,软件窗口的消息传播……但是以上的责任的转移,或者说在责任链上的移动,各个责任类不知道具体顺序和下一个责任,链条的组装过程是环境类(或客户端完成的)。
责任链模式和状态模式的区别:
不可否认,状态模式也好,责任链模式也罢,都能解耦和优化大量的逻辑判断, 责任链模式使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。 将这个对象练成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 各个责任类不知道也没必要知道下一个责任对象是谁!由环境类统一设置顺序和谁连接到链条, 谁不连接到链条……从代码中我们可以看出,职责链在client(环境类)连接,也就是说, 如果我们的生产线一旦改变,比如说我们不需要美容了,我们需要增加新的组装项目了, 或者是先组装车头后,直接请求去保存到仓库……这都是很容易实现的,职责链模式要比状态模式灵活很多。 但是,这时候有人要问,既然他们都可以解决逻辑判断的分支过多的问题, 那么,是不是责任链模式比状态模式好呢? 职责链模式过于灵活,在客户端使用时,需要环境去确定下一个对象是谁, 一些列的set操作……在多次设置的时候很容易出问题, 而且状态模式是一个对象的内在状态发生改变(一个对象,相对比较稳定,处理完一个对象下一个对象的处理一般都已确定), 而职责链模式是多个对象之间的改变(多个对象之间的话,就会出现某个对象不存在的情景,就像之前讲状态模式时的公司请假系统,可能存在不同级别,不同类型员工请假流程不一样,此时用状态模式不太好), 这也说明他们两个模式处理的情况不同。
这两个设计模式最大的区别就是:
- 状态模式是让各个状态对象自己知道其下一个处理的对象是谁,即在编译时便设定。 相当于If ,else-if,else-if……, 设计思路是把逻辑判断转移到各个State类的内部实现(相当于If,else If), 执行时客户端通过调用环境—Context类的方法来间接执行状态类的行为,客户端不直接和状态交互。
- 职责链模式中的各个对象并不指定其下一个处理的对象到底是谁,只有在客户端才设定某个类型的链条, 请求发出后穿越链条,直到被某个职责类处理或者链条结束。 本质相当于swich-case,设计思路是把各个业务逻辑判断封装到不同职责类,且携带下一个职责的对应引用, 但不像状态模式那样需要明确知道这个引用指向谁,而是在环境类设置链接方式或者过程。 使用时,向链的第一个子类的执行方法传递参数就可以。客户端去通过环境类调用责任链,全自动运转起来。
针对具体业务,有人用状态模式,从头到尾提前定义好下一个处理的对象,有人采用责任链, 随时都有可能调整链的顺序……甚至不复杂的业务判断,或者只需要使用一次的情景下, 那就没必要搞这些鸡毛模式,本着够用原则和具体业务的适合原则!