美文网首页
2019-08-21责任链模式

2019-08-21责任链模式

作者: 猫KK | 来源:发表于2019-08-21 20:26 被阅读0次

将多个对象连成一条链,并沿这条链传递请求,直到有对象处理它为止

就如同请假一样,你请假给你的直系领导,但是直系领导没有权利批假,他又会向他的领导提申请一样。一重一重的往上传递,直到有人能处理,在一重一重的回调回来。用代码来解释:
定义一个领导的接口:

public interface ILeader {
    /**
     * 请假结果
     *
     * @return 返回请假结果
     */
    String result(int date);
}

定义链,即上一级领导:

public interface ILeave {

    /**
     * 设置领导
     *
     * @param nextLeader 领导
     */
    void nextLeader(ILeader nextLeader);
}

抽象一个领导,封装公用方法:

    
public abstract class Leave implements ILeave, ILeader {

    //持有上级领导的引用
    protected ILeader leader;

    @Override
    public void nextLeader(ILeader nextLeader) {
        this.leader = nextLeader;
    }
}

具体一个领导:

//组长
public class TeamLeader extends Leave {

    //自己可以批的假的天数
    private final int batchLeaveDate = 2;

    @Override
    public String result(int date) {
        if (batchLeaveDate >= date) {
            //自己可以批这个假
            return "TeamLeader:请假批准";
        }
        //自己不可以批这个假,并且他有上级领导
        if (leader != null) {
            return leader.result(date);
        }
        return "TeamLeader:没人能批假";
    }
}

定义一个普通员工:

public class Staff extends Leave {

    @Override
    public String result(int date) {
        //向上级请假,得到请假结果
        return leader.result(date);
    }
}

再多定义几个领导:

//经理
public class Manager extends Leave {
    //自己可以批的假的天数
    private final int batchLeaveDate = 4;

    @Override
    public String result(int date) {
        if (batchLeaveDate >= date) {
            //自己可以批这个假
            return "Manager:请假批准";
        }
        if (leader != null) {
            return leader.result(date);
        }
        return "Manager:没人能批假";
    }
}
    
//总经理
public class GeneralManager extends Leave {
    //自己可以批的假的天数
    private final int batchLeaveDate = 10;

    @Override
    public String result(int date) {
        if (batchLeaveDate >= date) {
            //自己可以批这个假
            return "GeneralManager:请假批准";
        }
        if (leader != null) {
            return leader.result(date);
        }
        return "GeneralManager:没人能批假";
    }
}
    
//老板
public class Boss extends Leave {
    //自己可以批的假的天数
    private final int batchLeaveDate = 30;

    @Override
    public String result(int date) {
        if (batchLeaveDate >= date) {
            //自己可以批这个假
            return "Boss:请假批准";
        }
        if (leader != null) {
            return leader.result(date);
        }
        return "Boss:走人吧,没有这么长的假";
    }
}

在客户端中使用:

public class Client {
    public static void main(String[] args) {
        //创建各个领导对象,即多个对象
        Boss boss = new Boss();
        GeneralManager generalManager = new GeneralManager();
        Manager manager = new Manager();
        TeamLeader teamLeader = new TeamLeader();
        //设置各个领导的上级领导,即构成一条链
        teamLeader.nextLeader(manager);
        manager.nextLeader(generalManager);
        generalManager.nextLeader(boss);

        //创建员工对象
        Staff staff = new Staff();
        //设置员工对象的领导
        staff.nextLeader(teamLeader);
        //请假一天,得到结果
        String result = staff.result(1);
        System.out.println(result);
    }
}

到这里,责任链模式就完成,还有一种写法,就是Okhttp的拦截器,需要多一个辅助类,下面仿照okhttp的责任链,重新定义 ILeader 接口:

public interface ILeader {
    //得到结果
    String result(Chain chain);

    //定义一个链的接口
    interface Chain {
        //定义需要传递的参数,即请假天数
        int leaveDate();
        //得到结果
        String proceed(int date);
    }
}

增加一个辅助类:

//实现ILeader.Chain接口
public class Company implements ILeader.Chain {

    private List<ILeader> leaders;
    private int index, leaveDate;
    //构造方法传递所有的领导列表,当前的领导下标,需要传递的参数
    public Company(List<ILeader> leaders, int leaveDate, int index) {
        this.leaders = leaders;
        this.index = index;
        this.leaveDate = leaveDate;
    }

    @Override
    public int leaveDate() {
        //返回需要传递的参数
        return leaveDate;
    }

    @Override
    public String proceed(int date) {
        //在 proceed 方法中从新创建一个Company对象,注意 index 下标加 1 
        //代表了下一个领导
        Company next = new Company(leaders, date, index + 1);
        //根据下标,获取领导
        ILeader leader = leaders.get(index);
         //调用领导的处理方法,处理这个请假
        return leader.result(next);
    }
}

重新编写领导:

//实现ILeader 接口
public class TeamLeader implements ILeader {

    //自己可以批的假的天数
    private final int batchLeaveDate = 2;

    @Override
    public String result(Chain chain) {
        //通过辅助类,获取传递的参数,即请假天数
        int leaveDate = chain.leaveDate();
        //判断自己是否可以批假
        if (batchLeaveDate >= leaveDate) {
            return "TeamLeader:批假了";
        }
        //不可以,通过辅助类来走下一个领导
        return chain.proceed(chain.leaveDate());
    }
}

再来一个领导

public class Boss implements ILeader {

    //自己可以批的假的天数
    private final int batchLeaveDate = 30;

    @Override
    public String result(Chain chain) {
        int leaveDate = chain.leaveDate();
        if (batchLeaveDate >= leaveDate) {
            return "Boss:批假了";
        }
        return "走人吧";
    }
}

在 Client 中使用:

    
public class Client {
    public static void main(String[] args) {
        //定义领导列表
        List<ILeader> leaders = new ArrayList<>();
        //往列表中新添加领导,注意,先添加会先经过
        //因为是通过index下表来获取的
        leaders.add(new TeamLeader());
        leaders.add(new Boss());
        //创建辅助类Company,注意,index 初始值为0,需要传递的参数和下面一致即可
        Company company = new Company(leaders, 35, 0);
        //调用请假,获取请假结果
        String result = company.proceed(35);
        System.out.println(result);
    }
}

上面这种就是仿照okhttp的拦截器写的责任链,相比上一种,就不需要逐个对象设置链。注意,使用这种写法一定有一个是返回结果的,即总会有一个终结点,否则会出现数组下标越界的错误。

相关文章

网友评论

      本文标题:2019-08-21责任链模式

      本文链接:https://www.haomeiwen.com/subject/thtwsctx.html