状态模式在具体状态里设置了下一状态。

而职责链模式是在客户端代码里设置了下一状态的处理对象。

如果状态模式里的任何一环缺失,将导致事情无法进行下去。职责链模式的链式在客户端连接的,也就是说,如果我们请假,请假制度一旦改变,比如说我们不需要班长,或者是先请求老师后直接请求主任或者中间多了一个环节,都是很容易实现的,所以,职责链模式要比状态模式灵活很多。

小时候写日记都是这么写的:上午七点起床,八点之前洗脸刷牙吃早饭,十二点之前好好上课,中午一点,吃午饭,下午两点到六点,上课,下课,找请假,明天妈妈要带我去姥姥家,九点之前,看动画片,九点钟,收拾去姥姥家的东西,十点以后,睡觉。

我们把请假这块在充实一下:找班长请假,班长只能请半天,否则班长向老师申请,如果请假时间超过一周,老师要跟副年级主任请示,如果请假超出一个月,主任要跟年级正主任请示,然后被批准,或不被批准。

如果用编程语言描述这两件事情,应该是这个样子的。

[html] view plaincopy

 
  1. public class DayWork
  2. {
  3. private int hour;
  4. public void writeProgram()
  5. {
  6. if (hour < 7)
  7. {
  8. System.out.println("当前时间:" + hour + "点 睡觉");
  9. }
  10. else if (hour = 7)
  11. {
  12. System.out.println("当前时间:" + hour + "洗脸刷牙吃早饭");
  13. }
  14. else if (hour < 12)
  15. {
  16. System.out.println("当前时间:" + hour + "点 好好上课");
  17. }
  18. else if(hour=1)
  19. {
  20. System.out.println("当前时间:" + hour + "点 吃午饭");
  21. }
  22. else if(hour<18)
  23. {
  24. System.out.println("当前时间:" + hour + "点 好好学习");
  25. }
  26. }
  27. public int getHour()
  28. {
  29. return hour;
  30. }
  31. public void setHour(int hour)
  32. {
  33. this.hour = hour;
  34. }
  35. }
  36. //客户端代码
  37. public class Main
  38. {
  39. public static void main(String[] args)
  40. {
  41. DayWork work = new Work();
  42. work.setHour(9);
  43. work.writeProgram();
  44. work.setHour(10);
  45. work.writeProgram();
  46. work.setHour(12);
  47. work.writeProgram();
  48. work.setHour(13);
  49. work.writeProgram();
  50. work.setHour(14);
  51. work.writeProgram();
  52. }
  53. }

而请假的代码和这个差不多,if 请半天,班长请,else if 一周以内,老师请 else if 一个月以内 副主任请,else
超过一个月 主任请。

可是,拿日记例子来看,过多的if分支并不是一件好事,它首先不满足开闭原则,一旦需要修改整个IF语句都需要修改,责任没有费解,也不符合单一职责原
则,我们希望分解整个行为,把状态的判断逻辑转移到表示不同状态的一系列类当中,把复杂的判断逻辑简化,这就是我们所说的状态模式。

状态模式结构图:

状态模式代码实现:

[html] view
plain
copy

 
  1. //State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为
  2. public interface State
  3. {
  4. public void handle(Context context);
  5. }
  6. //ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
  7. public class ConcreteStateA implements State
  8. {
  9. public void handle(Context context)
  10. {
  11. context.setState(new ConcreteStateB());
  12. }
  13. }
  14. public class ConcreteStateB implements State
  15. {
  16. public void handle(Context context)
  17. {
  18. context.setState(new ConcreteStateA());
  19. }
  20. }
  21. //Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态
  22. public class Context
  23. {
  24. private State   state;
  25. public Context(State state)
  26. {
  27. this.state = state;
  28. }
  29. public void request()
  30. {
  31. state.handle(this);
  32. }
  33. public State getState()
  34. {
  35. return state;
  36. }
  37. public void setState(State state)
  38. {
  39. this.state = state;
  40. System.out.println("当前状态:" + state.getClass().getName());
  41. }
  42. }
  43. //客户端代码
  44. public class Main
  45. {
  46. public static void main(String[] args)
  47. {
  48. Context context = new Context(new ConcreteStateA());
  49. context.request();
  50. context.request();
  51. context.request();
  52. context.request();
  53. }
  54. }

状态模式将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。

而且,状态模式把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。

请假问题也是一个很复杂的条件表达式,安理说用状态模式是可以使用的。

但是,这里有一个问题,就是,如果班长请假了,用状态模式的道理讲,就是其他学生都请不了假了,也就是如果状态模式中任何一环缺失的话,这个事件都无法进行下去,怎么办?

这就需要我们的职责链模式。

结构图:

代码实现:

[html] view
plain
copy

 
  1. <pre name="code" class="html">// Chain of Responsibility pattern -- Structural example
  2. using System;
  3. // "Handler"
  4. abstract class Handler
  5. {
  6. // Fields
  7. protected Handler successor;
  8. // Methods
  9. public void SetSuccessor( Handler successor )
  10. {
  11. this.successor = successor;
  12. }
  13. abstract public void HandleRequest( int request );
  14. }
  15. // "ConcreteHandler1"
  16. class ConcreteHandler1 : Handler
  17. {
  18. // Methods
  19. override public void HandleRequest( int request )
  20. {
  21. if( request >= 0 && request < 10 )
  22. Console.WriteLine("{0} handled request {1}",
  23. this, request );
  24. else
  25. if( successor != null )
  26. successor.HandleRequest( request );
  27. }
  28. }
  29. // "ConcreteHandler2"
  30. class ConcreteHandler2 : Handler
  31. {
  32. // Methods
  33. override public void HandleRequest( int request )
  34. {
  35. if( request >= 10 && request < 20 )
  36. Console.WriteLine("{0} handled request {1}",
  37. this, request );
  38. else
  39. if( successor != null )
  40. successor.HandleRequest( request );
  41. }
  42. }
  43. // "ConcreteHandler3"
  44. class ConcreteHandler3 : Handler
  45. {
  46. // Methods
  47. override public void HandleRequest( int request )
  48. {
  49. if( request >= 20 && request < 30 )
  50. Console.WriteLine("{0} handled request {1}",
  51. this, request );
  52. else
  53. if( successor != null )
  54. successor.HandleRequest( request );
  55. }
  56. }
  57. /// <summary>
  58. /// Client test
  59. /// </summary>
  60. public class Client
  61. {
  62. public static void Main( string[] args )
  63. {
  64. // Setup Chain of Responsibility
  65. Handler h1 = new ConcreteHandler1();
  66. Handler h2 = new ConcreteHandler2();
  67. Handler h3 = new ConcreteHandler3();
  68. h1.SetSuccessor(h2);
  69. h2.SetSuccessor(h3);
  70. // Generate and process request
  71. int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
  72. foreach( int request in requests )
  73. h1.HandleRequest( request );
  74. }
  75. }

职责链模式(Chain of
Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象练成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

从代码中我们可以看出,职责链模式的链式在客户端连接的,也就是说,如果我们请假,请假制度一旦改变,比如说我们不需要班长,或者是先请求老师后直接请求主任或者中间多了一个环节,都是很容易实现的,所以,职责链模式要比状态模式灵活很多。

但是,这时候是不是有人要问,都可以解决If分支过多,是不是职责链模式比状态模式好呢,还是那句话,存在即合理,职责链模式虽然灵活,但是他过于灵活,
我们在使用时需要确定下一个对象是谁,在多次设置的时候很容易出问题,所以,这时候用状态模式就比较好,就像我们记录一天的行为,事情已经发生,如果用职
责链模式就显得画蛇添足了。

从定义来看,状态模式是一个对象的内在状态发生改变(一个对象,相对比较稳定,处理完一个对象下一个对象的处理一般都已确定),而职责链模式是多个对象之
间的改变(多个对象之间的话,就会出现某个对象不存在的现在,就像请假例子中的班长或者老师可能缺勤),这也说明他们两个模式处理的情况不同。

其实,这两个设计模式最大的区别就是状态模式是让各个状态对象自己知道其下一个处理的对象是谁,即在编译时便设定好了的;

而职责链模式中的各个对象并不指定其下一个处理的对象到底是谁,只有在客户端才设定。用我们通俗的编程语言来说,就是

状态模式:
  相当于If else if else;
  设计路线:各个State类的内部实现(相当于If,else If内的条件)
  执行时通过State调用Context方法来执行。
职责链模式:
  相当于Swich case
  设计路线:客户设定,每个子类(case)的参数是下一个子类(case)。
 
使用时,向链的第一个子类的执行方法传递参数就可以。

就像对设计模式的总结,有的人采用的是状态模式,从头到尾,提前一定定义好下一个处理的对象是谁,而我采用的是职责链模式,随时都有可能调整链的顺序,这也算是依个人口味均匀添加了吧!!!适合就好!

转自:http://blog.csdn.net/laner0515/article/details/7383872

职责链模式vs状态模式区别的更多相关文章

  1. 基于.net 职责链来实现 插件模式

    插件式的例子 QQ电脑管家,有很多工具列表,点一下工具下载后就可以开始使用了 eclipse ,X Server 等等 插件式的好处 插件降低框架的复杂性,把扩展功能从框架中剥离出来 让第三方有机会来 ...

  2. .net 职责链来实现 插件模式

    .net 职责链来实现 插件模式 插件式的例子 QQ电脑管家,有很多工具列表,点一下工具下载后就可以开始使用了 eclipse ,X Server 等等 插件式的好处 插件降低框架的复杂性,把扩展功能 ...

  3. 【设计模式】 模式PK:策略模式VS状态模式

    1.概述 行为类设计模式中,状态模式和策略模式是亲兄弟,两者非常相似,我们先看看两者的通用类图,把两者放在一起比较一下. 策略模式(左)和状态模式(右)的通用类图. 两个类图非常相似,都是通过Cont ...

  4. 《大话》之 策略模式 Vs 状态模式

    一.简介: 策略模式: 背景:商店要打折销售,各种版本的销售方式,让小菜心烦意乱 内容:    定义算法家族,分别封装起来,让他们之间可以户型替换,此模式让算法的变化,不会影响到使用算法的用户. 图文 ...

  5. Java设计模式之策略模式与状态模式

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 一.策略模式定义 定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们之间可以相互替换,策略模式可以在不影响客户端的情况下发生变化. ...

  6. java - 策略模式、状态模式、卫语句,避免多重if-else(转)

    前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...

  7. Java重构-策略模式、状态模式、卫语句

    前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...

  8. 【转】Java重构-策略模式、状态模式、卫语句

    前言 当代码中出现多重if-else语句或者switch语句时.弊端之一:如果这样的代码出现在多处,那么一旦出现需求变更,就需要把所有地方的if-else或者switch代码进行更改,要是遗漏了某一处 ...

  9. Java 策略模式和状态模式

    本文是转载的,转载地址:大白话解释Strategy模式和State模式的区别 先上图: 本质上讲,策略模式和状态模式做得是同一件事:去耦合.怎么去耦合?就是把干什么(语境类)和怎么干(策略接口)分开, ...

随机推荐

  1. easyui源码翻译1.32--Window(窗口)

    前言 扩展自$.fn.panel.defaults.使用$.fn.window.defaults重写默认值对象.下载该插件翻译源码 窗口控件是一个浮动和可拖拽的面板可以用作应用程序窗口.默认情况下,窗 ...

  2. velocity-1.7中vm文件的存放位置

    velocity-1.7中关于vm文件存放 demo: public class App_example1 { public App_example1() { String propfile=&quo ...

  3. redis消息队列

    http://blog.csdn.net/21aspnet/article/details/7455032

  4. ActionBar官方教程(10)ActionBar的下拉列表模式

    Adding Drop-down Navigation As another mode of navigation (or filtering) for your activity, the acti ...

  5. OSFM Tables

    OSFM - Oracle Shop Floor Management 1. (N) Shop Floor Manager > Lot Based Jobs (B: New) Status: U ...

  6. win2003+IIS6+PHP5.3.8+MSSQL2008的安装配置

  7. 登陆与注册以及Session

    Session  保存状态是在 登陆窗口  检查用户密码的动作上执行 .Models namespace 注册与登陆以及Session.Models { public class UserBF { p ...

  8. bzoj3697

    一开始又看错题,以为同样路径上不同的休息站是算不同路径,后来发现休息站只是路径合法的条件毫无疑问是树的分治,下面我们只要考虑计算能建休息站的路径我们把阳看作路径权值为1,阴作为路径权值-1点分治之后, ...

  9. bzoj1705

    话说这题很久以前就写过,然后好像一直忘了写题解…… 以前看这道题还觉得挺难的,现在觉得好水 首先朴素的想法肯定是动归 f[i,j]表示到处理到第i根电线,最终高度为j的最小花费 f[i,j]:=min ...

  10. TFS源代码管理

    一.服务器配置 1.创建一个Visual Studio Online账户 打开VS,选择团队资源管理器(视图菜单下),然后在团队资源管理器中选择注册Team Foundation Service,打开 ...