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

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

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

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

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

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

[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. 怎么修改tomcat默认访问首页

    一般情况下安装好tomcat之后我们的默认访问首页是index了,但我们如果要修改或增加一个默认首页,我们可参考下面办法来解决. 通过 ip:port 访问到的是 tomcat 的管理页面,其他常规部 ...

  2. SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-006-定义切面使用xml

    一. you can also define pointcuts that can be used across multiple aspects by placing the <aop:poi ...

  3. 【Linux远程管理】SSH协议远程管理

    SSH(Secure Shell)协议.命令行界面(CLI)下的远程管理工具,几乎所有的操作系统都有,区别于Telnet,SSH在进行数据传送时会对数据进行加密,所以SSH是比较安全的协议.几乎所有的 ...

  4. BNU29368:Check the Identity(栈)

    Just determine whether an algebraic expression can always simplify to zero. Input The first line con ...

  5. make menuconfig出错

    make[1]: *** [scripts/kconfig/mconf] Error 1 make: *** [menuconfig] Error 2 fixed: sudo apt-get inst ...

  6. C# XML序列化操作菜单

    鉴于之前写的一篇博文没使用XML序列化来操作菜单,而且发现那还有一个问题,就是在XML菜单的某个菜单节点前加上一些注释代码的就不能读取,现在使用XML序列化后可以很方便的读取,故在此写一写.   XM ...

  7. Xcode6新建的工程没有Frameworks文件夹了?!原来是这样

    http://stackoverflow.com/questions/24181062/default-frameworks-missing-in-xcode-6-beta They are impo ...

  8. 【转】MFC中用CFile读取和写入文件2

    原文网址:http://blog.sina.com.cn/s/blog_623a7fa40100hh1u.html CFile提供了一些常用的操作函数,如表1-2所示. 表1-2  CFile操作函数 ...

  9. Linux文件类型与扩展名

    Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念.我们通过一般应用程序而创建的比如file.txt.file.tar.gz ,这些文件虽然要用不同的程序来打开,但放在Linux文 ...

  10. Java笔记(二十三)……Map集合

    Map接口 Map<K,V> 该集合存储的是键值对,成对往集合里存,而且要保证键的唯一性 常用方法 添加 Vput(K key, V value) voidputAll(Map<? ...