设计模式之责任链模式

从击鼓传花说起:

击鼓传花是一种热闹而又紧张的饮酒游戏。在酒宴上宾客依次坐定位置,由一人击鼓,击鼓的地方与传花的地方是分开的,以示公正。开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在某人手中,则该人就得饮酒。
在这里插入图片描述
击鼓传花便是责任链模式的应用。责任链可能是一条直线、一个环链或者一个树结构的一部分。
在这里插入图片描述
责任链模式涉及到的角色如下所示:

  • 抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。

  • 具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。

责任链模式1:

事件经过责任链的每一个环节,各个环节只处理"属于"自己的那一部分。
(举例:去医院看病, 挂号–> 医生开检查单 --> 做检查 -->医生看病 -->病房抓药)
在这里插入图片描述
代码实现:
参数:

public class MyDto {

    private String type;

    private String name;

    public MyDto(String type, String name) {
        this.type = type;
        this.name = name;
    }

    //toString 
    //get...
    //set...
}

抽象处理者角色:

public interface MyHandle {
    Object handMethod(MyDto dto);
}

具体处理者1:

public class OneMyHandle implements MyHandle {
    @Override
    public Object handMethod(MyDto dto) {
    
        if ("111".equals(dto.getType())) {
            //业务逻辑处理...
        }
        return null;
    }
}

具体处理者2:

public class TwoMyHandle implements MyHandle {
    @Override
    public Object handMethod(MyDto dto) {

         if ("222".equals(dto.getType())) {
            //业务逻辑处理...
        }

        return null;
    }
}

客户端:

public class TestForMyHandle {

    public static void main(String[] args) {

        MyHandle h1 = new OneMyHandle();
        MyHandle h2 = new TwoMyHandle();
        MyDto myDto = new MyDto("type", "name");
        List<MyHandle> list = new ArrayList<>(2);
        list.add(h1);
        list.add(h2);
		//遍历执行每一个"环节"
        for (MyHandle handle : list) {
            handle.handMethod(myDto);
        }
    }
}

责任链模式2:

在责任链模式1中,事件会经过链上的每一环节,有些情况是没必要经过全部环节的,可以在链上的任意一个环节进行中断返回。
在这里插入图片描述

比如下面这个场景: 在公司请假,请半天或1天假需要组长审批即可,请2-3天假,需要直系经理进行审批,请4-5天假需要部门经理审批,请超过5天假期需要公司高层审批。
在这里插入图片描述
入参:

public class HDto {

    //请假天数
    private Integer days;

    //请假原因
    private String reason;

    //请假人
    private String name;

    public HDto(Integer days, String reason, String name) {
        this.days = days;
        this.reason = reason;
        this.name = name;
    }
    //get set toString...
}

出参:

public class HVo {

    //t: 同意请假  f: 拒绝请假
    private Boolean result;

    //审批原因
    private String msg;

    public HVo(Boolean result, String msg) {
        this.result = result;
        this.msg = msg;
    }
    //get set toString
}

抽象处理者角色:

public abstract class Handle {

    //下一个处理者
    Handle handle;

	//处理事件
    public HVo dealAbsence(HDto dto) {
        return null;
    }
	
	//设置下一个处理者
    public void setNextHandle(Handle handle) {
        this.handle = handle;
    }


	//获取下一个处理者
    public Handle getNextHandle() {
        return handle;
    }
}

具体处理者(组长):

public class TeamLeaderHandle extends Handle {
    @Override
    public HVo dealAbsence(HDto dto) {

        if (dto.getDays() < 2) {

            //其他逻辑判断
            // ...
            System.out.println(String.format("组长批准,%s: 请假%d天成功",dto.getName(),dto.getDays()));
            return new HVo(true, "组长批准, 请假成功");
        }

        //交给下一个处理
        return getNextHandle().dealAbsence(dto);
    }
}

具体处理者(直系经理):

public class DirectManagerHandle extends Handle {
    @Override
    public HVo dealAbsence(HDto dto) {
        if (1 < dto.getDays() && dto.getDays() < 4) {

            //其他逻辑判断
            System.out.println(String.format("直系经理批准,%s: 请假%d 天成功",dto.getName(),dto.getDays()));

            return new HVo(true, "直系经理批准, 请假成功");
        }
        //交给下一个处理
        return getNextHandle().dealAbsence(dto);
    }
}

具体处理者(部门经理):

public class DeptManagerHandle extends Handle {
    @Override
    public HVo dealAbsence(HDto dto) {
        if (3 < dto.getDays() && dto.getDays() < 6) {

            //其他逻辑判断
            System.out.println(String.format("部门经理批准,%s: 请假%d 天成功",dto.getName(),dto.getDays()));

            return new HVo(true, "部门经理批准, 请假成功");
        }

        //交给下一个处理
        return getNextHandle().dealAbsence(dto);
    }
}

具体处理者(公司高管):

public class TopHandle extends Handle {
    @Override
    public HVo dealAbsence(HDto dto) {

        if (dto.getDays() > 5) {
            //业务逻辑判断
            //....

            System.out.println(String.format("公司高管批准,%s: 请假%d 天成功", dto.getName(), dto.getDays()));

            return new HVo(true, "公司高管批准, 请假成功");
        }
        return null;
    }
}

测试:

public class TestForHandle {

    public static void main(String[] args) {

        Handle handle1 = new TeamLeaderHandle();
        Handle handle2 = new DirectManagerHandle();
        Handle handle3 = new DeptManagerHandle();
        Handle handle4 = new TopHandle();
		
		//上一个处理者持有下一个处理者
        handle1.setNextHandle(handle2);
        handle2.setNextHandle(handle3);
        handle3.setNextHandle(handle4);

       handle1.dealAbsence(new HDto(1, "肚子疼", "张三"));
       System.out.println("----------------------------------------------");
     
       handle1.dealAbsence(new HDto(3, "肚子疼", "张三"));
       System.out.println("----------------------------------------------");

       handle1.dealAbsence(new HDto(5, "肚子疼", "张三"));
       System.out.println("----------------------------------------------");

       handle1.dealAbsence(new HDto(7, "肚子疼", "张三"));
    }
}

在这里插入图片描述

其他

Tomcat的filter属于第二种模式的应用。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值