首页 > 编程语言 >Java设计模式之责任链模式

Java设计模式之责任链模式

时间:2023-10-10 16:34:50浏览次数:39  
标签:leave Java 请求 Author 处理 责任 Handler 设计模式 public

1.1.概述

在现实生活中,常常会出现这样的事例:一个请求有多个对象可以处理,但每个对象的处理条件或权限不同。例如,公司员工请假,可批假的领导有部门负责人、副总经理、总经理等,但每个领导能批准的 天数不同,员工必须根据自己要请假的天数去找不同的领导签名,也就是说员工必须记住每个领导的姓名、电话和地址等信息,这增加了难度。这样的例子还有很多,如找领导出差报销、生活中的“击鼓传 花”游戏等。 定义: 又名职责链模式,为了避免请求发送者与多个请求处理者耦合在一起,将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处 理它为止。

1.2.结构

职责链模式主要包含以下角色: • 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。 • 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。 • 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。

1.3.案例实现

现需要开发一个请假流程控制系统。请假一天以下的假只需要小组长同意即可;请假1天到3天的假还需要部门经理同意;请求3天到7天还需要总经理同意才行。 类图如下:

代码如下:  
/**
 * @version v1.0
 * @ClassName: LeaveRequest
 * @Description: 请假条类
 * @Author: 黑马程序员
 */
public class LeaveRequest {
    //姓名
    private String name;

    //请假天数
    private int num;

    //请假内容
    private String content;

    public LeaveRequest(String name, int num, String content) {
        this.name = name;
        this.num = num;
        this.content = content;
    }

    public String getName() {
        return name;
    }

    public int getNum() {
        return num;
    }

    public String getContent() {
        return content;
    }
}


/**
 * @version v1.0
 * @ClassName: Handler
 * @Description: 抽象处理者类
 * @Author: 黑马程序员
 */
public abstract class Handler {

    protected final static int NUM_ONE = 1;
    protected final static int NUM_THREE = 3;
    protected final static int NUM_SEVEN = 7;

    //该领导处理的请假天数区间
    private int numStart;
    private int numEnd;

    //声明后续者(声明上级领导)
    private Handler nextHandler;

    public Handler(int numStart) {
        this.numStart = numStart;
    }

    public Handler(int numStart, int numEnd) {
        this.numStart = numStart;
        this.numEnd = numEnd;
    }

    //设置上级领导对象
    public void setNextHandler(Handler nextHandler) {
        this.nextHandler = nextHandler;
    }

    //各级领导处理请求条的方法
    protected abstract void handleLeave(LeaveRequest leave);

    //提交请求条
    public final void submit(LeaveRequest leave) {
        //该领导进行审批
        if (this.nextHandler != null && leave.getNum() > this.numEnd) {
            //提交给上级领导进行审批
            this.nextHandler.submit(leave);
        } else {
            this.handleLeave(leave);
            System.out.println("流程结束!");
        }
    }
}


/**
 * @version v1.0
 * @ClassName: GroupLeader
 * @Description: 小组长类(具体的处理者)
 * @Author: 黑马程序员
 */
public class GroupLeader extends Handler {

    public GroupLeader() {
        super(0,Handler.NUM_ONE);
    }

    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("小组长审批:同意");
    }
}


/**
 * @version v1.0
 * @ClassName: GroupLeader
 * @Description: 部门经理类(具体的处理者)
 * @Author: 黑马程序员
 */
public class Manager extends Handler {

    public Manager() {
        super(Handler.NUM_ONE,Handler.NUM_THREE);
    }

    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("部门经理审批:同意");
    }
}


/**
 * @version v1.0
 * @ClassName: GroupLeader
 * @Description: 总经理类(具体的处理者)
 * @Author: 黑马程序员
 */
public class GeneralManager extends Handler {

    public GeneralManager() {
        super(Handler.NUM_THREE,Handler.NUM_SEVEN);
    }

    protected void handleLeave(LeaveRequest leave) {
        System.out.println(leave.getName() + "请假" + leave.getNum() + "天," + leave.getContent() + "。");
        System.out.println("总经理审批:同意");
    }
}

/**
 * @version v1.0
 * @ClassName: Client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class Client {
    public static void main(String[] args) {
        //创建一个请假条对象
        LeaveRequest leave = new LeaveRequest("小明",5,"身体不适");

        //创建各级领导对象
        GroupLeader groupLeader = new GroupLeader();
        Manager manager = new Manager();
        GeneralManager generalManager = new GeneralManager();

        //设置处理者链
        groupLeader.setNextHandler(manager);
        manager.setNextHandler(generalManager);


        //小明提交请假申请
        groupLeader.submit(leave);
    }
}

 1.4.优缺点

1 优点: • 降低了对象之间的耦合度 该模式降低了请求发送者和接收者的耦合度。 • 增强了系统的可扩展性 可以根据需要增加新的请求处理类,满足开闭原则。 • 增强了给对象指派职责的灵活性 当工作流程发生变化,可以动态地改变链内的成员或者修改它们的次序,也可动态地新增或者删除责任。 • 责任链简化了对象之间的连接 一个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。 • 责任分担  每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则   2 缺点: • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。 •  对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。 • 职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。

1.5.源码解析

在javaWeb应用开发中,FilterChain是职责链(过滤器)模式的典型应用,以下是Filter的模拟 实现分析: • 模拟web请求Request以及web响应Response
/**
 * @version v1.0
 * @ClassName: Request
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public interface Request {
}


/**
 * @version v1.0
 * @ClassName: Response
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public interface Response {
}

 • 模拟web过滤器Filter

 
/**
 * @version v1.0
 * @ClassName: Filter
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public interface Filter {
    public void doFilter(Request req,Response res,FilterChain c);
}

 •模拟实现具体过滤器

 
/**
 * @version v1.0
 * @ClassName: FirstFilter
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class FirstFilter implements Filter {
    public void doFilter(Request req, Response res, FilterChain chain) {
        System.out.println("过滤器1 前置处理");

        // 先执行所有request再倒序执行所有response
        chain.doFilter(req, res);

        System.out.println("过滤器1 后置处理");
    }
}



/**
 * @version v1.0
 * @ClassName: FirstFilter
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class SecondFilter implements Filter {
    public void doFilter(Request req, Response res, FilterChain chain) {
        System.out.println("过滤器2 前置处理");

        // 先执行所有request再倒序执行所有response
        chain.doFilter(req, res);

        System.out.println("过滤器2 后置处理");
    }
}

 • 模拟实现过滤器链FilterChain

/**
 * @version v1.0
 * @ClassName: FilterChain
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class FilterChain { //过滤器链

    private List<Filter> filters = new ArrayList<Filter>();

    private int index = 0;

    // 链式调用
    public FilterChain addFilter(Filter filter) {
        this.filters.add(filter);
        return this;
    }

    public void doFilter(Request request, Response response) {
        if (index == filters.size()) {
            return;
        }
        Filter filter = filters.get(index);
        index++;
        filter.doFilter(request, response, this);
    }
}

 

  • 测试类
/**
 * @version v1.0
 * @ClassName: Client
 * @Description: TODO(一句话描述该类的功能)
 * @Author: 黑马程序员
 */
public class Client {
    public static void main(String[] args) {
        Request  req = null;
        Response res = null ;

        FilterChain filterChain = new FilterChain();
        filterChain.addFilter(new FirstFilter()).addFilter(new SecondFilter());
        filterChain.doFilter(req,res);
    }
}

 

标签:leave,Java,请求,Author,处理,责任,Handler,设计模式,public
From: https://www.cnblogs.com/carlors/p/17755045.html

相关文章

  • Java创建PKCS12证书Http请求
    //证书地址publicstaticfinalStringPATH="XX.pfx";//密码publicstaticfinalStringPASSWORD="aaa";publicstaticCloseableHttpClientinitSSLConfig()throwsException{//证书类型KeyStorekeyStore=KeyStore.getInstanc......
  • 详解如何通过JavaScript实现函数重载
    有的同学在开发中可能遇到过一个困扰,但是很少有人去解决这个问题,我这用一个例子展现出来constsearcher={};searcher.findAll=()=>{console.log("查询所有用户");};searcher.findByName=(name)=>{console.log("按照用户名称查询");};searcher.findByFirstN......
  • Android Studio可以编译但Flutter提示无法定位java runtime
    AndroidStudio可以编译但Flutter提示无法定位javaruntime下面我们重点讲一下“UnabletofindbundledJavaversion”报错问题到AndroidStudio安装目录下注意:有些AndroidStudio可能是“jbr”文件,不用管jbr文件,直接复制一份jbr文件在同一路经,再把复制的文件改名为“jre”文......
  • java stream 操作map根据key或者value排序的实现
    javastream操作map根据key或者value排序的实现publicclassTest02{publicstaticvoidmain(String[]args){List<FundBenchMarkInfo>fundBenchMarkList=newArrayList<>();fundBenchMarkList.add(newFundBenchMarkInfo("2",new......
  • Composite 组合模式简介与 C# 示例【结构型3】【设计模式来了_8】
    〇、简介1、什么是组合设计模式?一句话解释:  针对树形结构的任意节点,都实现了同一接口,他们具有相同的操作,可以通过某一操作来遍历全部节点。组合模式通过使用树形结构来组合对象,用来表示部分以及整体层次。组合模式属于结构型模式,多用于递归。官方意图描述:将对象组合成树形......
  • JavaSE---SortedSet(TreeSet)
    SortedSet概述A{@linkSet}thatfurtherprovidesatotalorderingonitselements.提供元素排序的set;Theelementsareorderedusingtheir{@linkplainComparablenatural ordering},orbya{@linkComparator}typicallyprovidedatsortedsetcre......
  • 前端面试八股文 JavaScript
    前端面试八股文JavaScript谈谈对原型链的理解在JavaScript中,每个对象都有一个原型对象proto,指向其构造函数的原型对象prototype。当我们创建一个新的实例对象时,这个对象会从其构造函数的原型对象prototype中继承属性和方法。如果实例对象自身没有某个属性或方法,但是其构造函数......
  • 设计模式之 Observer Pattern观察者模式
    观察者模式Observer  Observer模式为组件向相关接收方【广播】消息提供了灵活的方法;  该模式定义了对象一到多的依赖关系,这样当对象改变状态时,将自动通知并更新他所有的依赖对象;  优点    抽象了主体与Observer之间的耦合关系;    支持广播方式的通信......
  • 基于Java Swing和BouncyCastle的证书生成工具
    "Almostnoonewillrememberwhathehadjustnotinterested."-Nobody“几乎没有人会记得他所丝毫不感兴趣的事情。”——佚名0x00大纲目录0x00大纲0x01前言0x02技术选型0x03需求分析目标用户用户故事功能需求安全需求兼容需求性能需求0x04原型设计主窗体RSA根......
  • Java设计模式之工厂设计模式
    1.1.概述需求:设计一个咖啡店点餐系统。设计一个咖啡类(Coffee),并定义其两个子类(美式咖啡【AmericanCoffee】和拿铁咖啡【LatteCoffee】);再设计一个咖啡店类(CoffeeStore),咖啡店具有点咖啡的功能。具体类的设计如下: 在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new......