美文网首页
责任链模式

责任链模式

作者: Tyhj | 来源:发表于2019-02-12 15:20 被阅读0次

定义

使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

使用场景

  • 多个对象可以处理同一请求,但具体由那个对象处理则在运行时动态决定
  • 在请求处理者不确定的情况下向多个对象中的一个提交一个请求
  • 需要动态的指定一组对象处理请求

理解

感觉很简单,不管下面如何去实现,只要构建了一条链,把请求按照这条链传递下去,避免请求者和接收者之间的耦合,就是责任链模式

举个栗子

网上最多的例子,解决审批权限问题;过年我要请假在家里多玩几天,请一个月假,项目经理说他最多审批2天的,多了找主管,主管说,一个月太过分了,他只能审批5天以内的,一个月要找老板,找老板,老板说小问题,准了;

用户接口

public interface User {
    /**
     * 请假审批
     */
    void approval();
}

请假类

public class Vacation {
    /**
     * 请假天数
     */
    int days;

    public Vacation(int days) {
        this.days = days;
    }
}

去请假

public void leave(Vacation vacation) {
        User boss=new Boss();
        User director=new Director();
        User manager=new Manager();
        
        if (vacation.days <= 2) {
            manager.approval();
        } else if (vacation.days <= 5) {
            director.approval();
        } else {
            boss.approval();
        }
    }

这个写法肯定是有问题的吧,看到if-else就知道是不符合开闭原则,修改容易引起错误;而且代码臃肿;具体的处理逻辑我们放到了这个场景类里面也不是很合理,应该放到各个用户中处理

重构

修改用户接口

public abstract class User {

    /**
     * 上一级领导
     */
    protected User nextUser;

    /**
     * 处理请假
     *
     * @param vacation 请假
     */
    public final void handleRequest(Vacation vacation) {
        if (vacation.days <= limit()) {
            approval();
        } else {
            if (null != nextUser) {
                nextUser.handleRequest(vacation);
            }
        }
    }

    /**
     * 能审批的天数
     *
     * @return 天数
     */
    public abstract int limit();

    /**
     * 请假审批
     */
    public abstract void approval();
}

主管实现类,其他差不多

public class Director extends User {

    @Override
    public int limit() {
        return 5;
    }

    @Override
    public void approval() {
        System.out.println("主管审批通过");
    }
}

去请假

public void leave(Vacation vacation) {
        User boss=new Boss();
        User director=new Director();
        User manager=new Manager();
        
        manager.nextUser=director;
        director.nextUser=boss;

        manager.handleRequest(vacation);
    }

1.责任链模式与 if-else 相比,耦合性要低一些,因为它将条件判定分散到各个处理类中,并且这些处理类的优先处理顺序可以随意的设定,并且如果想要添加新的 user 类也是十分简单的,这符合开放闭合原则。
2.责任链模式感觉也更灵活,思路更清晰一些

功能链

标准的责任链模式,一个请求只能被一个节点处理,感觉其实应用的场景不是很多;一个请求被多个节点处理的场景要多一个,其实做法是差不多的;比如实现一个过滤器

public class MsgProcessor {
    /**
     * 字符串信息
     */
    String msg;

    public MsgProcessor(String msg) {
        this.msg = msg;
    }

    /**
     * 过滤信息
     *
     * @return
     */
    public String process() {
        String str = msg;
        //过滤msg中的HTML标记
        str = str.replace("<", "&lt;").replace(">", "&gt;");
        //过滤敏感词
        str = str.replace("敏感", "");
        return str;
    }

}

将过滤的方法都放在process方法中,这样不遵循开闭原则,修改过滤规则容易引起错误;

提取出过滤接口

public interface StringFilter {
    /**
     * 过滤操作
     *
     * @param msg 源字符串
     * @return 过滤后字符串
     */
    String doFilter(String msg);
}

实现过滤HTML标记

public class HtmlFilter implements StringFilter {
    @Override
    public String doFilter(String msg) {
        msg = msg.replace("<", "&lt;").replace(">", "&gt;");
        return msg;
    }
}

过滤处理

public class MsgProcessor {
    /**
     * 字符串信息
     */
    String msg;

    List<StringFilter> filterList = new ArrayList<>();

    public MsgProcessor(String msg) {
        this.msg = msg;
    }

    /**
     * 过滤信息
     *
     * @return
     */
    public String process() {
        String str = msg;
        for (StringFilter filter : filterList) {
            str = filter.doFilter(str);
        }
        return str;
    }

    /**
     * 添加过滤方法
     *
     * @param filter
     */
    public void addFilter(StringFilter filter) {
        filterList.add(filter);
    }

}

调用

MsgProcessor msgProcessor=new MsgProcessor(":),敏感信息,<script>");
msgProcessor.addFilter(new HtmlFilter());
msgProcessor.process();

新增过滤方法只需要实现接口就好了

相关文章

网友评论

      本文标题:责任链模式

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