设计模式 - 责任链模式

设计模式 - 责任链模式

  • 1、责任链模式的应用
    • 1.1、啥是责任链模式
    • 1.2、责任链模式的优缺点
  • 2、责任链模式小试牛刀
    • 2.1、实现场景描述
    • 2.2、常规实现
    • 2.3、责任链模式实现
      • 2.3.1、请求方
      • 2.3.2、处理方
      • 2.3.3、业务方法
      • 2.3.4、执行结果
  • 3、总结

1、责任链模式的应用

1.1、啥是责任链模式

 
在责任链模式里,很多对象由每一个对象对其下家的引用,而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
 

1.2、责任链模式的优缺点

 
优点:责任链模式非常显著的优点是,将请求和处理分开,将两者解耦,提高系统的灵活性。
 
该模式有以下两个缺点:

  • 性能问题:每个请求都是从链头遍历到链尾,当链路较长时,造成性能是个问题。
  • 调试问题:当链路较长时,因为采用类似递归的方法,调试的时候逻辑可能比较复杂。
     

注意事项:链路节点的数量需要控制,避免出现超长链路的情况。
 
一般的做法是在 Handler 中设置一个最大节点数量,在 setNextHandler 方法中判断是否已经达到最大节点数,超过则不允许该链路建立,避免无意的造成超长链路节点数,导致系统性能破坏。

 

2、责任链模式小试牛刀

2.1、实现场景描述

 
场景:尊重、保护女性是美德。假如某地女性出门都喜欢有家人陪伴,比如未出嫁的女性喜欢父亲陪伴,出嫁的女性喜欢丈夫陪伴,出嫁丧夫的女性喜欢子女陪伴。
现在一个女性出门前会向家人提出需求,然后家人会对需求做出反馈。
 

2.2、常规实现

 

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Women {
   private int type = 0;
   private String request;
}

public interface IHandler{
   public void handlerMessage(Women women);
}

public class Father implements IHandler {
   public void handlerMessage(Women women) {
      // todo…… 父亲处理业务逻辑
   }
}

public class Husband implements IHandler {
   public void handlerMessage(Women women) {
      // todo…… 丈夫处理业务逻辑
   }
}

public class Son implements IHandler {
   public void handlerMessage(Women women) {
      // todo…… 儿子处理业务逻辑
   }
}

public class Client {
 public static void main(String[] args) {
   IHandler father = new Father();
   IHandler husband = new Husband();
   IHandler son = new Son();
   Women women = new Women(1, "我想去逛街");
   
   if (women.getType() == 1) { // 未结婚的少女,找父亲陪伴
     father.handlerMessage(women);
   } else if (women.getType() == 2) {  // 已婚少妇,找丈夫陪伴
     husband.handlerMessage(women);
   } else if (women.getType() == 3) { // 已婚桑夫,找子女陪伴
     son.handlerMessage(women);
   } else { // 无人陪伴很惨……
      // 兜底逻辑 todo……
   }
 }  
}

 

2.3、责任链模式实现

 

2.3.1、请求方

 

package com.design.mode.chain.of.responsibility.entity;
/**
 * @author peng
 */
public interface IWomen {
    /** 获取实体状态:0-未知状态,1-未婚(需要父亲响应),
     *  2-已婚(需要丈夫响应),3-已婚亡夫(需要子女响应)*/
    public int getType();

    /** 请求 **/
    public String getRequest();

    /** 名称 **/
    public String getName();
}
package com.design.mode.chain.of.responsibility.entity;

/**
 * @author peng
 */
public class Women implements IWomen {

    private int type;
    private String name;
    private String request;

    public Women (int type,String name, String request) {
        this.type = type;
        this.name = name;
        this.request = request;
    }

    @Override
    public int getType() {return this.type;}

    @Override
    public String getRequest() {return this.request;}

    @Override
    public String getName() {return this.name;}
}

 

2.3.2、处理方

 

package com.design.mode.chain.of.responsibility.handler;
import com.design.mode.chain.of.responsibility.entity.IWomen;

/**
 * 基础处理器
 * @author peng
 */
public abstract class BaseHandler {
    /** 父亲 **/
    public final static int FATHER_TYPE = 1;
    /** 丈夫 **/
    public final static int HUSBAND_TYPE = 2;
    /** 儿子 **/
    public final static int SON_TYPE = 3;
    
    /** 下一个处理者 **/
    private BaseHandler nextHandler;

    /** 当前处于哪一个级别,默认为0 **/
    private int level = 0;

    public BaseHandler(int level) {this.level = level;}

    /**
     * 该方法用于你如果不能处理该请求,则设置下一个处理者 
     */
    public void setNextHandler(BaseHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    public final void handlerMessage(IWomen women) {
        if (women.getType() == this.level) {
            this.deal(women);
        } else {
            // 下一个处理者如果不为空,则交由他处理
            if (this.nextHandler != null) {
               this.nextHandler.handlerMessage(women);
            } else {  // 无下一个责任人,则进行忽略
               System.out.println("----- 女性"+ women.getName() +"沟通需求 ------");
               System.out.println("------无处理责任人,当拒绝处理--------\n");
            }
        }
    }

    /** 处理请求的抽象接口 **/
    public abstract void deal(IWomen women);

}
package com.design.mode.chain.of.responsibility.handler;
import com.design.mode.chain.of.responsibility.entity.IWomen;

/**
 * @author peng
 */
public class FatherHandler extends BaseHandler{

    // 通过构造函数,设置Father的处理级别
    public FatherHandler() {super(BaseHandler.FATHER_TYPE);}

    @Override
    public void deal(IWomen women) {
        System.out.println("----- 女性"+ women.getName() +"向父亲沟通需求 ------");
        System.out.println("----- 女性"+ women.getName() +"的需求是:" + women.getRequest());
        System.out.println("----- 父亲的答复是: 好的,注意安全,早点回家!\n");
    }
}
package com.design.mode.chain.of.responsibility.handler;
import com.design.mode.chain.of.responsibility.entity.IWomen;

/**
 * @author peng
 */
public class HusbandHandler extends BaseHandler {
    // 通过构造函数,设置Husband的处理级别
    public HusbandHandler() {super(BaseHandler.HUSBAND_TYPE);}

    @Override
    public void deal(IWomen women) {
        System.out.println("----- 女性"+ women.getName() +"向丈夫沟通需求 ------");
        System.out.println("----- 女性"+ women.getName() +"的需求是:" + women.getRequest());
        System.out.println("----- 丈夫的答复是: 好的,我陪你去吧!\n");
    }
}
package com.design.mode.chain.of.responsibility.handler;
import com.design.mode.chain.of.responsibility.entity.IWomen;

/**
 * @author peng
 */
public class SonHandler extends BaseHandler {
    // 通过构造函数,设置Son的处理级别
    public SonHandler() {super(BaseHandler.SON_TYPE);}

    @Override
    public void deal(IWomen women) {
        System.out.println("----- 女性"+ women.getName() +"向儿子沟通需求 ------");
        System.out.println("----- 女性"+ women.getName() +"的需求是:" + women.getRequest());
        System.out.println("----- 儿子的答复是: 好的,我陪你去吧!\n");
    }
}

 

2.3.3、业务方法

 

package com.design.mode.chain.of.responsibility;

import com.design.mode.chain.of.responsibility.entity.IWomen;
import com.design.mode.chain.of.responsibility.entity.Women;
import com.design.mode.chain.of.responsibility.handler.BaseHandler;
import com.design.mode.chain.of.responsibility.handler.FatherHandler;
import com.design.mode.chain.of.responsibility.handler.HusbandHandler;
import com.design.mode.chain.of.responsibility.handler.SonHandler;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * 责任链模式测试类
 * @author peng
 */
public class ChainOfResponsibilityClient {

    public static void main(String[] args) {
        // 大街上随机挑选10位女性
        Random rand = new Random();
        List<IWomen> womenList = new ArrayList<>(BigInteger.TEN.intValue());
        for (int k = 1 ; k <= BigInteger.TEN.intValue(); k++) {
            womenList.add(new Women(rand.nextInt(4),String.valueOf(k), "我想去逛商场,吃美食!"));
        }
        // 定义处理类
        BaseHandler fatherHandler = new FatherHandler();
        BaseHandler husbandHandler = new HusbandHandler();
        BaseHandler sonHandler = new SonHandler();
        // 设置请求顺序
        fatherHandler.setNextHandler(husbandHandler);
        husbandHandler.setNextHandler(sonHandler);
        // 上面每一个女性都去表达自己的需求,并得到响应
        for (IWomen women : womenList) {
            fatherHandler.handlerMessage(women);
        }
    }
}

 

2.3.4、执行结果

 

----- 女性1向父亲沟通需求 ------
----- 女性1的需求是:我想去逛商场,吃美食!
----- 父亲的答复是: 好的,注意安全,早点回家!

----- 女性2向丈夫沟通需求 ------
----- 女性2的需求是:我想去逛商场,吃美食!
----- 丈夫的答复是: 好的,我陪你去吧!

----- 女性3向父亲沟通需求 ------
----- 女性3的需求是:我想去逛商场,吃美食!
----- 父亲的答复是: 好的,注意安全,早点回家!

----- 女性4沟通需求 ------
------无处理责任人,当拒绝处理--------

----- 女性5向儿子沟通需求 ------
----- 女性5的需求是:我想去逛商场,吃美食!
----- 儿子的答复是: 好的,我陪你去吧!

----- 女性6沟通需求 ------
------无处理责任人,当拒绝处理--------

----- 女性7向丈夫沟通需求 ------
----- 女性7的需求是:我想去逛商场,吃美食!
----- 丈夫的答复是: 好的,我陪你去吧!

----- 女性8向儿子沟通需求 ------
----- 女性8的需求是:我想去逛商场,吃美食!
----- 儿子的答复是: 好的,我陪你去吧!

----- 女性9向丈夫沟通需求 ------
----- 女性9的需求是:我想去逛商场,吃美食!
----- 丈夫的答复是: 好的,我陪你去吧!

----- 女性10向父亲沟通需求 ------
----- 女性10的需求是:我想去逛商场,吃美食!
----- 父亲的答复是: 好的,注意安全,早点回家!

 

3、总结

 
责任链接的核心类,就是抽象类 IHandler、抽象类的子实现子类、还有就是业务类。当然在具体的使用前,我们需要根据业务场景灵活使用。
对于每个抽象类的实现类,只需要关注自己的业务逻辑,抽象类的实现类只专注怎样做事,具体自己需要处理哪一种事,那就交给父类去决定。抽象类实现了请求传递的功能,抽象类实现请求的处理,这也是设计模式单一职责原则的体现。

举例:银行里面有存款业务,然后也有很多币种类型(人民币、美元、日元)。A、B、C 三个工作人员都负责存款业务,现在行长想提高工作效率,分配: A处理人民币存款业务、B处理美元存款业务、C处理日元存款业务。 对于A、B、C而言,他们只需要关注怎么把自己的存款业务做好,他们不需要关心币种类型分配的问题。如果现在又有了欧元的存款业务,行长只需要再分配一个D员工处理,而A、B、C三个员工可以对欧元业务的事情无感知。
该例子 A、B、C、D、行长,可以分别理解为java中的一个类,各自负责自己的事情,单一职责。

public abstract class Handler {
  private Handler nextHandler;
  // 设置下一个处理者
  public void setNextHandler(Handler nextHandler) {
     this.nextHandler = nextHandler;
  } 
  // 每个处理者都有一个处理级别   
  protected abstract Level getHandlerLevel();
  // 每个处理者都要实现处理任务的方法
  protected abstract Response echo(Request request);  
  // 每一个处理者必须对请求做出处理
  public final Response hanldeMessage(Request request) {
     Response response = null;
     // 判断该级别是否需要自己处理
     if (this.getHandlerLevel().equals(request.getRequestLevel())) {
          response = this.echo(request);
     } else { // 不是自己处理的级别,判断是否有下一个处理者
          if (this.nextHandler != null) {
             response = this.nextHandler.hanldeMessage(request);
          } else {
             // 没有处理者,可以根据业务做兜底逻辑     
          }
     }
     return response;
  }
}


public class ConcreateHandler extends Handler {
  protected Response echo(Request request) {
    return null;  // 处理自己具体的实现
  }
  protected Level getHandlerLevel(){
    return null;  // 设置自己的处理级别 
  }
}

public class Level{
  // 定义一个请求和处理等级
}

public class Request{
  // 请求的等级
  public Level getRequestLevel() {
   return null;
  }
}

public class Response{
  // 处理者返回的数据
}

public class Client{
    // 声明责任链处理节点
    Handler handler1 = new ConcreateHandler1();
    Handler handler2 = new ConcreateHandler2();
    Handler handler3 = new ConcreateHandler3();
    // 设置责任链中的阶段顺序 1->2->3
    handler1.setNext(handler2);
    handler2.setNext(handler3);
    // 提交请求,返回结果
    Response response = handlder1.handlerMessage(new Request);
}

你可能感兴趣的:(设计模式,设计模式,责任链模式,java)