本文是对职责链设计模式的应用(变种),所以假设读者已经掌握了职责链设计模式,职责链模式只会应景简介。

本文主要内容:

  1. 需求(ShitCode)
  2. 职责链模式简介
  3. 设计理念
  4. 代码演示(消除if)
  5. 应用总结

一、需求(ShitCode)

  1. package com.cnblogs.kmpp;
  2.  
  3. public class ShitCode {
  4.  
  5. public void doSomething(ParameterObject parameterObject)
  6. {
  7. if (parameterObject != null)//判断输入参数是否为null
  8. {
  9. if (parameterObject.getId() > 0)//判断输入参数的ID是否大于0
  10. {
  11. int code = getCodeById(parameterObject.getId());//业务逻辑判断
  12. if (code > 0)
  13. {
  14. //有可能还会有其他的判断
  15. //do something vaild
  16. }
  17. }
  18. }
  19. }
  20.  
  21. private int getCodeById(int id) {
  22. return 0;
  23. }
  24. }

上面这段ShitCode很明显,有大量的if判断:在满足众多if后才去做具体的事情,上面ShitCode只有三个if,实际情况中有可能会更多。怎么办?

二、职责链模式简介

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

上图是职责链模式的经典类图。如果了解这个设计模式,上面定义中说到的链路(successor)是由ConcreteHandler在HandleRequest的时候按照某种逻辑来指定的。比如请假,经理和总监是两个不同的ConcreteHandler,hr设定当请假天数大于5天时,需要总监来处理,这个时候经理会设置自己的successor为总监,从而形成一个链路。

三、设计理念

再次回到ShitCode。仔细看看ShitCode可以抽象为:当条件1满足的时候再去判断条件2。。。一直到条件N不满足或者最后一个条件满足为止(没有successor)。这是一个递归的过程。

所以这个条件之间的调度是可以抽象出来,本文开始说了,本次的应用是对职责链设计模式的应用,是一个变种。因为这个条件之间的调度是可以抽象出来,所以这个调度是可以放在父类中进行执行,而无需在每一个ConcreteHandle执行。这点便是对本文对于职责链设计模式的修改点。

四、代码演示(消除if)

4.1 父类:定义算法骨架

验证器的抽象,递归调度条件验证器。

  1. package com.cnblogs.kmpp;
  2.  
  3. public abstract class AbsctractValidator
  4. {
  5. private AbsctractValidator validatorSuccessor;
  6.  
  7. protected void setValidatorSuccessor(AbsctractValidator validatorSuccessor)//这个和经典的职责链模式一样,用于设置下一个
  8. {
  9. this.validatorSuccessor = validatorSuccessor;
  10. }
  11.  
  12. public boolean validate(ParameterObject parameterObject)
  13. {
  14. boolean result=this.validateSelfLogic(parameterObject);//验证当前逻辑
  15. if(result)//当前逻辑满足
  16. {
  17. if(this.validatorSuccessor!=null)//有下一个验证器
  18. {
  19. return this.validatorSuccessor.validate(parameterObject);//继续验证
  20. }
  21. }
  22. return result;//返回最终结果
  23. }
  24.  
  25. public abstract boolean validateSelfLogic(ParameterObject parameterObject);
  26.  
  27. }

4.2 第一个条件参数验证的ConcreteValidator

只需实现自己的参数验证逻辑,无需关注其他事情

  1. package com.cnblogs.kmpp;
  2.  
  3. public class ParameterValidator extends AbsctractValidator
  4. {
  5. @Override
  6. public boolean validateSelfLogic(ParameterObject parameterObject)
  7. {
  8. System.out.println("in validator1");
  9. if(parameterObject==null)
  10. {
  11. System.out.println("parameterObject is null");
  12. return false;
  13. }
  14. if(parameterObject.getId()<=0)
  15. {
  16. System.out.println("parameterObject.getId()<=0");
  17. return false;
  18. }
  19. return true;
  20. }
  21. }

4.3 第二个业务逻辑验证的ConcreteValidator

只需实现自己的业务逻辑验证逻辑,无需关注其他事情

  1. package com.cnblogs.kmpp;
  2.  
  3. public class BusinessLogicValidator extends AbsctractValidator
  4. {
  5. @Override
  6. public boolean validateSelfLogic(ParameterObject parameterObject)
  7. {
  8. System.out.print("in validator2");
  9. int code=this.getCodeById(parameterObject.getId());
  10. if(code>0)
  11. {
  12. System.out.println("code>0");
  13. return true;
  14. }
  15. return false;
  16. }
  17.  
  18. private int getCodeById(int id)
  19. {
  20. return 0;
  21. }
  22. }

当有新需求时候还可以继续扩展新的Validator。

4.4 Cient调用

  1. package com.cnblogs.kmpp;
  2.  
  3. public class Client {
  4. public static void main(String args[])
  5. {
  6. ParameterValidator parameterValidator=new ParameterValidator();
  7. BusinessLogicValidator businessLogicValidator=new BusinessLogicValidator();
  8. parameterValidator.setValidatorSuccessor(businessLogicValidator);
  9. parameterValidator.validate(null);
  10. }
  11. }

上面的代码中已经消除成功消除了if。且上面的代码BusinessLogicValidator是不会执行的,因为validate(null)。第一个ParameterValidator最后会返回false。

五、总结

本文主要说职责链模式,其实仔细看看上面用到的也是模版方法:父类定义算法骨架,子类实现部分逻辑。

在本文的设计中,AbstractValidator完整的定义了算法骨架以及调度的抽象,每一个ConcreteValidator只需要实现真正属于自己验证的逻辑,无需关注其他事情,满足单一职责原则,那当然也满足了Open-Close原则:

  1. 每一个validator可以随便修改而不影响其他Validator
  2. 可以继续继承AbstractValidator实现新的Validator

设计模式要活学活用,不要过于拘泥于格式。上面的设计其实还可以衍生出很多变种的。

设计模式-利用职责链模式消除if的更多相关文章

  1. php设计模式之职责链模式

    <?php /** * @desc php设计模式之职责链模式(责任链模式) 定义:顾名思义,责任链模式为请求创建了一个接收者对象的链.这种模式给予请求的类型,对请求的发送者和接收者进行解耦.这 ...

  2. 设计模式之职责链模式(JAVA实现)

    学习netty框架时,看到有人说netty用到了设计模式的职责链模式,学习一下职责链模式,主要参考大话设计模式. 主要场景: 小菜想要加薪,向经理提出加薪请求,经理没有权限,经理交由总监处理,总监也没 ...

  3. 深入理解JavaScript系列(38):设计模式之职责链模式

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

  4. 设计模式:职责链模式(Chain Of Responsibility)

    定  义:使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止. 结构图: 处理请求类: //抽象处理类 abs ...

  5. 设计模式之职责链模式(Chain of Responsibility)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  6. JavaScript设计模式_10_职责链模式

    职责链模式的定义是:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止.职责链模式的名字非常形象,一系列可能 ...

  7. php实现设计模式之 职责链模式

    <?php /** * 职责链模式 * * 为解除请求的发送者和接收者之间的耦合,而使用多个对象都用机会处理这个请求,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它 * 抽象 ...

  8. JS常用的设计模式(15)—— 职责链模式

    职责链模式是一个对象A向另一个对象B发起请求,如果B不处理,可以把请求转给C,如果C不处理,又可以把请求转给D.一直到有一个对象愿意处理这个请求为止. 打个比方,客户让老板写个php程序.老板肯定不写 ...

  9. 设计模式之职责链模式(Chain of Responsibility)

    职责链模式原理: 职责链模式和装饰模式以及组合模式类似的地方是都维持着指向父类的指针, 不同点是职责链模式每个子类都继承父类的指针及每个之类都维持着指向父类的指针,而组合模式与装饰模式是组合类鱼装饰类 ...

随机推荐

  1. vue项目创建流程和使用

    vue项目的创建 npm run dev 让项目执行起来 #下载vuex npm install vuex --save#下载axiosnpm install axios --save 当我们生成项目 ...

  2. Linux c编程:线程属性

    前面介绍了pthread_create函数,并且当时的例子中,传入的参数都是空指针,而不是指向pthread_attr_t结构的指针.可以使用pthread_attr_t结构修改线程默认属性,并把这些 ...

  3. bug-3——onload,onbeforeunload,Onunload的区别

    window.onload事件设置页面加载时执行的动作,即进入页面的时候执行的动作.   window.onunload已经从服务器上读到了需要加载的新的页面,在即将替换掉当前页面时调用 一般用于设置 ...

  4. Write 语句

    ABAP Write 语句 转载▼http://blog.sina.com.cn/s/blog_5ccd375b0100ghhi.html   1.Write 叙述 ABAP/4 用来在屏幕上输出数据 ...

  5. python基础5 ---python文件处理

    python文件处理 一.文件处理的流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 二.文件的操作方法 1.文件打开模式格式: 文件句柄 = open('文件路径', ...

  6. php线程pthread实践

    php有线程吗?----有,但是需要扩展pthreads,扩展方式网上有一堆的教程,这是只做线程demo. file_put_contents(dirname(__FILE__).'/1.txt', ...

  7. jQuery自定义美化下拉框

    在线演示 本地下载

  8. 比较分析与数组相关的sizeof和strlen

    首先,我们要清楚sizeof是C/C++中的一个操作符,其作用就是返回一个对象或者类型所占的内存字节数. 而,strlen是一个函数,函数原型为: size_t strlen(const char * ...

  9. 在Treeview中节点的data属性中保存记录类型及其消除的办法

    一.保存记录类型在data指针中: procedure TForm1.getheaditems(pp:TfrxBand;hnode:THeadTreeNode;var i:Integer;var j: ...

  10. Jquery的load()

    我一直认为jquery的load函数是以GET方式请求另一个文件并加载到当前DOM里的.当我带参数加载一个ASP脚本时是这样做: $("#showData").load(" ...