设计模式--责任链模式

责任链模式(Chain of Responsibility Pattern)

责任链模式是一种行为模式,在责任链模式中,很多对象由每一个对象对其下家的引用而连接起来形成一条链。客户端应用在这个链上进行传递,直到链上的某一个对象决定处理此请求。发出请求的客户并不知道链上的哪一个对象最终处理这个请求。这使系统可以不影响客户端的情况下动态地重新组织和分配责任。
责任链模式涉及的角色如下:
1. 抽象处理者角色(Handler):定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回下家的引用。
2. 具体处理者角色(ConcreteHandler):具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于处理者持有下家引用,因此,如果需要,具体处理者可以访问下家。

介绍

意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
应用场景
1. 有多个对象处理同一个请求,具体由哪一个来处理还不确定,只有在运行时才能确定哪个对象处理的情况。
2. 消息有多个接收者,而接收对象又是不明确的情况。只需要向其中一个对象发出消息,由其内部具体处理。
3. 同一个消息的多个处理对象可能会动态地增加或者减少,需要动态地指定的情况。
优点:1. 降低耦合度。它将请求的发送者和接收者解耦。2. 简化了对象。使得对象不需要知道链的结构。3. 增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4. 增加新的请求处理类很方便。
缺点:1. 不能保证请求一定被接收。2. 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。3. 可能不容易观察运行时的特征,有碍于除错。
注意事项:在JAVA WEB中遇到很多应用。

实现

关于实现过程中,我们模拟一个学生请假的过程,学生请假,如果学生请假时间比较短,可以直接跟班长汇报一声即可,如果时间较长可以找班主任审批,如果时间过长,则需要汇报校长进行审批。在该模式中,抽象出来的逻辑即是学生请假(请求),(班长,老师,校长)处理者进行处理。在此抽象中,班长,老师,校长可作为一个责任链(处理学生请假请求)。

步骤 1

我们构造一个学生接口,该接口定义学生的行为。
IStudent.java

package com.study.ResponsibilityPattern;

/**
 * 学生接口
 * @author admin
 *
 */
public interface IStudent {

    /**
     * 获取学生生病状态(用数字0,1,2模拟)
     * 0:学生生病状态轻微,班长可以直接处理
     * 1:学生生病状态一般,需要老师处理
     * 2:学生生病状态严重,需要校长处理
     * @return
     */
    public int getState();

    /**
     * 获得学生病假处理情况
     * @return
     */
    public String getRequestMessage();
}

构造一个处理者接口。用来处理学生的请假请求。
IHandler.java

package com.study.ResponsibilityPattern;

/**
 * 处理者接口
 * @author admin
 *
 */
public interface IHandler {

    /**
     * 处理学生请假
     * @param student
     */
    public void handleRequest(IStudent student);

    /**
     * 设置下一级流程处理者
     * @param handler
     */
    public void setHandler(IHandler handler);
}

定义一个抽象类,实现了处理者接口。抽象类中包含了一个下一级处理者的引用,同时定义了一个当前处理者可以处理的学生请假请求的生病状态。
AbstractHandler.java

package com.study.ResponsibilityPattern;

/**
 * 抽象处理类
 * @author admin
 */
public abstract class AbstractHandler implements IHandler{

    private int state;

    private IHandler handler;


    public AbstractHandler(int state) {
        this.state = state;
    }

    public abstract void process(IStudent student);

    public void handleRequest(IStudent student) {
        if(student != null) {
            if(student.getState() == getState()) {
                this.process(student);
            }else {
                if(this.handler != null) {
                    this.handler.handleRequest(student);
                }
            }
        }
    }

    public int getState() {
        return state;
    }

    public void setHandler(IHandler handler) {
        this.handler = handler;
    }
}

步骤 2

实现学生接口。学生实体类中有一个描述学生目前生病状态的关键字,state。
Student.java

package com.study.ResponsibilityPattern;

public class Student implements IStudent{

    private int state;

    public Student(int state) {
        this.state = state;
    }

    public int getState() {
        return this.state;
    }

    public String getRequestMessage() {
        return "可以请假";
    }

}

构造班长,教师,校长,三个具体的请求处理者。
班长
SquadLeaderHandler.java

package com.study.ResponsibilityPattern;

/**
 * 班长处理
 * @author admin
 *
 */
public class SquadLeaderHandler extends AbstractHandler{

    public SquadLeaderHandler() {
        super(0);
    }

    @Override
    public void process(IStudent student) {
        System.out.println("班长处理:" + student.getRequestMessage());
    }

}

教师
TeacherHandler.java

package com.study.ResponsibilityPattern;

/**
 * 老师处理者
 * @author admin
 *
 */
public class TeacherHandler extends AbstractHandler{

    public TeacherHandler() {
        super(1);
    }

    @Override
    public void process(IStudent student) {
        System.out.println("老师批复:" + student.getRequestMessage());
    }

}

校长
SchoolMasterHandler.java

package com.study.ResponsibilityPattern;


public class SchoolMasterHandler extends AbstractHandler{

    public SchoolMasterHandler() {
        super(2);
    }

    @Override
    public void process(IStudent student) {
        System.out.println("校长批复:" + student.getRequestMessage());
    }

}

步骤 3

在步骤3这个地方,我们要实现一个学生请假请求过来的时候,真正的处理流程。我们借鉴了外观模式的思想,构造了一个统一的处理请求的类,以此屏蔽学生请假请求的具体处理。
ProcessHandler.java

package com.study.ResponsibilityPattern;

/**
 * 这个类的出现主要的目的就是采用设计模式的另外一种思想(外观模式)
 * <直接对外提供一个接口,屏蔽系统内部处理>
 * @author admin
 */
public class ProcessHandler {

    private final IHandler squadLeaderHandler;

    private final IHandler teacherHandler;

    private final IHandler schoolMasterHandler;

    public ProcessHandler() {
        schoolMasterHandler = new SchoolMasterHandler();
        teacherHandler = new TeacherHandler();
        squadLeaderHandler = new SquadLeaderHandler();
        this.squadLeaderHandler.setHandler(this.teacherHandler);
        this.teacherHandler.setHandler(this.schoolMasterHandler);
    }

    private static ProcessHandler test = new ProcessHandler();

    public static ProcessHandler getInstance() {
        if(null != test) {
            return test;
        }else {
            test = new ProcessHandler();
            return test;
        }
    }

    /**
     * 处理消息
     * @param student
     */
    public void onMessage(IStudent student) {
        //交给第一级处理者进行处理(班长)
        this.squadLeaderHandler.handleRequest(student);
    }
}

步骤 4

测试类的构造。
Test.java

package com.study.ResponsibilityPattern;

import java.util.Random;

/**
 * 测试
 * @author admin
 *
 */
public class Test {

    public static void main(String[] args) {
        ProcessHandler handler = ProcessHandler.getInstance();
        for(int i = 0; i < 5; i ++) {
            //随机生成0-3之间的随机数(0,1,2)
            int state = new Random().nextInt(3);
            //构造学生对象
            IStudent student = new Student(state);
            //使用外观模式进行处理
            handler.onMessage(student);
        }
    }
}

验证输出。结果具有随机性,读者自行验证。

校长批复:可以请假
班长处理:可以请假
班长处理:可以请假
老师批复:可以请假
校长批复:可以请假
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值