职责链模式vs状态模式区别
状态模式在具体状态里设置了下一状态。
而职责链模式是在客户端代码里设置了下一状态的处理对象。
如果状态模式里的任何一环缺失,将导致事情无法进行下去。职责链模式的链式在客户端连接的,也就是说,如果我们请假,请假制度一旦改变,比如说我们不需要班长,或者是先请求老师后直接请求主任或者中间多了一个环节,都是很容易实现的,所以,职责链模式要比状态模式灵活很多。
小时候写日记都是这么写的:上午七点起床,八点之前洗脸刷牙吃早饭,十二点之前好好上课,中午一点,吃午饭,下午两点到六点,上课,下课,找请假,明天妈妈要带我去姥姥家,九点之前,看动画片,九点钟,收拾去姥姥家的东西,十点以后,睡觉。
我们把请假这块在充实一下:找班长请假,班长只能请半天,否则班长向老师申请,如果请假时间超过一周,老师要跟副年级主任请示,如果请假超出一个月,主任要跟年级正主任请示,然后被批准,或不被批准。
如果用编程语言描述这两件事情,应该是这个样子的。
- public class DayWork
- {
- private int hour;
- public void writeProgram()
- {
- if (hour < 7)
- {
- System.out.println("当前时间:" + hour + "点 睡觉");
- }
- else if (hour = 7)
- {
- System.out.println("当前时间:" + hour + "洗脸刷牙吃早饭");
- }
- else if (hour < 12)
- {
- System.out.println("当前时间:" + hour + "点 好好上课");
- }
- else if(hour=1)
- {
- System.out.println("当前时间:" + hour + "点 吃午饭");
- }
- else if(hour<18)
- {
- System.out.println("当前时间:" + hour + "点 好好学习");
- }
- }
- public int getHour()
- {
- return hour;
- }
- public void setHour(int hour)
- {
- this.hour = hour;
- }
- }
- //客户端代码
- public class Main
- {
- public static void main(String[] args)
- {
- DayWork work = new Work();
- work.setHour(9);
- work.writeProgram();
- work.setHour(10);
- work.writeProgram();
- work.setHour(12);
- work.writeProgram();
- work.setHour(13);
- work.writeProgram();
- work.setHour(14);
- work.writeProgram();
- }
- }
而请假的代码和这个差不多,if 请半天,班长请,else if 一周以内,老师请 else if 一个月以内 副主任请,else
超过一个月 主任请。
可是,拿日记例子来看,过多的if分支并不是一件好事,它首先不满足开闭原则,一旦需要修改整个IF语句都需要修改,责任没有费解,也不符合单一职责原
则,我们希望分解整个行为,把状态的判断逻辑转移到表示不同状态的一系列类当中,把复杂的判断逻辑简化,这就是我们所说的状态模式。
状态模式结构图:

状态模式代码实现:
- //State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
- public interface State
- {
- public void handle(Context context);
- }
- //ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
- public class ConcreteStateA implements State
- {
- public void handle(Context context)
- {
- context.setState(new ConcreteStateB());
- }
- }
- public class ConcreteStateB implements State
- {
- public void handle(Context context)
- {
- context.setState(new ConcreteStateA());
- }
- }
- //Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态
- public class Context
- {
- private State state;
- public Context(State state)
- {
- this.state = state;
- }
- public void request()
- {
- state.handle(this);
- }
- public State getState()
- {
- return state;
- }
- public void setState(State state)
- {
- this.state = state;
- System.out.println("当前状态:" + state.getClass().getName());
- }
- }
- //客户端代码
- public class Main
- {
- public static void main(String[] args)
- {
- Context context = new Context(new ConcreteStateA());
- context.request();
- context.request();
- context.request();
- context.request();
- }
- }
状态模式将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。
而且,状态模式把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
请假问题也是一个很复杂的条件表达式,安理说用状态模式是可以使用的。
但是,这里有一个问题,就是,如果班长请假了,用状态模式的道理讲,就是其他学生都请不了假了,也就是如果状态模式中任何一环缺失的话,这个事件都无法进行下去,怎么办?
这就需要我们的职责链模式。
结构图:

代码实现:
- <pre name="code" class="html">// Chain of Responsibility pattern -- Structural example
- using System;
- // "Handler"
- abstract class Handler
- {
- // Fields
- protected Handler successor;
- // Methods
- public void SetSuccessor( Handler successor )
- {
- this.successor = successor;
- }
- abstract public void HandleRequest( int request );
- }
- // "ConcreteHandler1"
- class ConcreteHandler1 : Handler
- {
- // Methods
- override public void HandleRequest( int request )
- {
- if( request >= 0 && request < 10 )
- Console.WriteLine("{0} handled request {1}",
- this, request );
- else
- if( successor != null )
- successor.HandleRequest( request );
- }
- }
- // "ConcreteHandler2"
- class ConcreteHandler2 : Handler
- {
- // Methods
- override public void HandleRequest( int request )
- {
- if( request >= 10 && request < 20 )
- Console.WriteLine("{0} handled request {1}",
- this, request );
- else
- if( successor != null )
- successor.HandleRequest( request );
- }
- }
- // "ConcreteHandler3"
- class ConcreteHandler3 : Handler
- {
- // Methods
- override public void HandleRequest( int request )
- {
- if( request >= 20 && request < 30 )
- Console.WriteLine("{0} handled request {1}",
- this, request );
- else
- if( successor != null )
- successor.HandleRequest( request );
- }
- }
- /// <summary>
- /// Client test
- /// </summary>
- public class Client
- {
- public static void Main( string[] args )
- {
- // Setup Chain of Responsibility
- Handler h1 = new ConcreteHandler1();
- Handler h2 = new ConcreteHandler2();
- Handler h3 = new ConcreteHandler3();
- h1.SetSuccessor(h2);
- h2.SetSuccessor(h3);
- // Generate and process request
- int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
- foreach( int request in requests )
- h1.HandleRequest( request );
- }
- }
职责链模式(Chain of
Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象练成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
从代码中我们可以看出,职责链模式的链式在客户端连接的,也就是说,如果我们请假,请假制度一旦改变,比如说我们不需要班长,或者是先请求老师后直接请求主任或者中间多了一个环节,都是很容易实现的,所以,职责链模式要比状态模式灵活很多。
但是,这时候是不是有人要问,都可以解决If分支过多,是不是职责链模式比状态模式好呢,还是那句话,存在即合理,职责链模式虽然灵活,但是他过于灵活,
我们在使用时需要确定下一个对象是谁,在多次设置的时候很容易出问题,所以,这时候用状态模式就比较好,就像我们记录一天的行为,事情已经发生,如果用职
责链模式就显得画蛇添足了。
从定义来看,状态模式是一个对象的内在状态发生改变(一个对象,相对比较稳定,处理完一个对象下一个对象的处理一般都已确定),而职责链模式是多个对象之
间的改变(多个对象之间的话,就会出现某个对象不存在的现在,就像请假例子中的班长或者老师可能缺勤),这也说明他们两个模式处理的情况不同。
其实,这两个设计模式最大的区别就是状态模式是让各个状态对象自己知道其下一个处理的对象是谁,即在编译时便设定好了的;
而职责链模式中的各个对象并不指定其下一个处理的对象到底是谁,只有在客户端才设定。用我们通俗的编程语言来说,就是
状态模式:
相当于If else if else;
设计路线:各个State类的内部实现(相当于If,else If内的条件)
执行时通过State调用Context方法来执行。
职责链模式:
相当于Swich case
设计路线:客户设定,每个子类(case)的参数是下一个子类(case)。
使用时,向链的第一个子类的执行方法传递参数就可以。
就像对设计模式的总结,有的人采用的是状态模式,从头到尾,提前一定定义好下一个处理的对象是谁,而我采用的是职责链模式,随时都有可能调整链的顺序,这也算是依个人口味均匀添加了吧!!!适合就好!
职责链模式vs状态模式区别的更多相关文章
- 基于.net 职责链来实现 插件模式
插件式的例子 QQ电脑管家,有很多工具列表,点一下工具下载后就可以开始使用了 eclipse ,X Server 等等 插件式的好处 插件降低框架的复杂性,把扩展功能从框架中剥离出来 让第三方有机会来 ...
- .net 职责链来实现 插件模式
.net 职责链来实现 插件模式 插件式的例子 QQ电脑管家,有很多工具列表,点一下工具下载后就可以开始使用了 eclipse ,X Server 等等 插件式的好处 插件降低框架的复杂性,把扩展功能 ...
- 【设计模式】 模式PK:策略模式VS状态模式
1.概述 行为类设计模式中,状态模式和策略模式是亲兄弟,两者非常相似,我们先看看两者的通用类图,把两者放在一起比较一下. 策略模式(左)和状态模式(右)的通用类图. 两个类图非常相似,都是通过Cont ...
- 《大话》之 策略模式 Vs 状态模式
一.简介: 策略模式: 背景:商店要打折销售,各种版本的销售方式,让小菜心烦意乱 内容: 定义算法家族,分别封装起来,让他们之间可以户型替换,此模式让算法的变化,不会影响到使用算法的用户. 图文 ...
- Java设计模式之策略模式与状态模式
版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. ...
- java - 策略模式、状态模式、卫语句,避免多重if-else(转)
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- Java重构-策略模式、状态模式、卫语句
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- 【转】Java重构-策略模式、状态模式、卫语句
前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...
- Java 策略模式和状态模式
本文是转载的,转载地址:大白话解释Strategy模式和State模式的区别 先上图: 本质上讲,策略模式和状态模式做得是同一件事:去耦合.怎么去耦合?就是把干什么(语境类)和怎么干(策略接口)分开, ...
随机推荐
- HDU3367+并查集应用
题意:找到一个这样的图,在这个图中,最多有一个环. 使得所有的边的和最大. 贪心+并查集 首先把边排序,然后开始分类讨论. 对于边ab(含有两个端点ab) 如果a,b是属于两个不同的集合 a b 是两 ...
- SpringMVC可以配置多个拦截后缀*.html和.do等
一个servlet可以配置多个servlet-mapping, 因此在xml文件中我们可以这样配置: <!-- springmvc配置 --> <servlet> <se ...
- HDOJ多校联合第六场
先一道一道题慢慢补上, 1009.题意,一棵N(N<=50000)个节点的树,每个节点上有一个字母值,给定一个串S0(|S0| <=30),q个询问,(q<=50000),每次询问经 ...
- Javascript实现摩斯码加密解密
原文地址 作者:liaoyu 摩尔斯电码是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母.数字和标点符号,是由美国人萨缪尔·摩尔斯在1836年发明. 每一个字符(字母或数字)对应不同的 ...
- 匿名函数和Lambda表达式
这个题目有点牵强,真不知道如何取一个比较中意的名称,写技术博客,我很少拘泥小节,但是注重细节,如果细节都出现问题了,那么这个博文也就失去了价值. 其实应该从委托说起,委托是C#中的一个重要的内容,记得 ...
- java的几种for循环方法
自从jdk升级为1.8以后,for循环又升级了 classic for classic foreach List.forEach() List.stream().forEach() List.para ...
- Java SE知识点
Java概述 Java的运行机制 JDK,JRE,JVM Java开发环境搭建 用记事本编写运行一个Hello World的完整过程 如何在Java中使用注释 使用Eclipse开发Java程序 使用 ...
- ☀【CSS3】box-sizing
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...
- -_-#【JS 优化】把 JS 放到底部
一开始为以为Javascript脚本尽量放到页面底部加载,是指所有的JS脚本都要放到底部,后来才发现, 并不完全是这样,这里所指的脚本是指那些在加载过程中要执行的脚本,所以一般的处理办法还是页面头部引 ...
- C# 根据Word模版生成Word文件
指定的word模版 2,生成word类 添加com Microsoft word 11.0 Object Library 引用 using System; using System.Collectio ...