【Android -- 面试】责任链模式

本文介绍了责任链模式的概念及其在代码组织中的应用。通过实例展示了如何使用责任链模式来处理需求分配,避免冗长的条件判断语句,提高代码可维护性和扩展性。并提供了一种优化方案,类似OkHttp的Interceptor实现,通过遍历责任链来找到合适的处理者。
摘要由CSDN通过智能技术生成

不断学习,做更好的自己!💪

视频号CSDN简书
欢迎打开微信,关注我的视频号:程序员朵朵点我点我

定义

百度百科的介绍:责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

维基百科的介绍:责任链模式在面向对象程式设计里是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。

我的介绍:顾名思义,责任链模式是一条链,链上有多个节点,每个节点都有各自的责任。当有输入时,第一个责任节点看自己能否处理该输入,如果可以就处理。如果不能就交由下一个责任节点处理。依次类推,直到最后一个责任节点。

定义总是有点文绉绉,还是看下下面的例子加深下理解吧。

例子

需求开发例子

假设现在有个需求来了,首先是实习生拿到这个需求。
如果实习生能够实现,直接实现。如果不行,他把这个需求交给初级工程师。
如果初级工程师能够实现,直接实现。如果不行,交给中级工程师。
如果中级工程师能够实现,直接实现。如果不行,交给高级工程师。
如果高级工程师能够实现,直接实现。如果不行,交给 CTO。
如果 CTO能够实现,直接实现。如果不行,直接跟产品说,需求不做。

买球篮例子

假设你现在有个篮球,然后想要买个球篮。
你肯定是到店里,让老板把所有尺寸的球篮拿出来。
然后你一个一个试。
第一个不行,就第二个。
第二个不行,就第三个。

直到找到合适的。

传统代码

给定一个输入值,根据输入值执行不同逻辑。

String input = "1";
if ("1".equals(input)) {
    //TODO do something
} else if ("2".equals(input)) {
    //TODO do something
} else if ("3".equals(input)) {
    //TODO do something
}

或者如下代码:

String input = "1";
switch (input) {
    case "1":
        //TODO do something
        break;
    case "2":
        //TODO do something
        break;
    case "3":
        //TODO do something
        break;
    default:
        //TODO do something
        break;
}

如果每个分支里面的逻辑比较简单,那还好,如果逻辑复杂,假设每个 case 大概要 100 行代码处理,有 10 个 case,一下子就出来一个「千行代码」文件,而且还不利于维护、测试和扩展。

下面来介绍如何通过责任链模式的妙用来拆分代码。

责任链模式代码

这里以上面场景为例子进行拆分代码说明。
1. 定义一个抽象类。

public abstract class BaseCase {
    // 为 true 表明自己可以处理该 case
    private boolean isConsume;

    public BaseCase(boolean isConsume) {
        this.isConsume = isConsume;
    }

    // 下一个责任节点
    private BaseCase nextCase;

    public void setNextCase(BaseCase nextCase) {
        this.nextCase = nextCase;
    }

    public void handleRequest() {
        if (isConsume) {
            // 如果当前节点可以处理,直接处理
            doSomething();
        } else {
            // 如果当前节点不能处理,并且有下个节点,交由下个节点处理
            if (null != nextCase) {
                nextCase.handleRequest();
            }
        }
    }

    abstract protected void doSomething();
}

2. 定义多个 case 来实现该抽象类,如下所示:

public class OneCase extends BaseCase {
    public OneCase(boolean isConsume) {
        super(isConsume);
    }

    @Override
    protected void doSomething() {
        // TODO do something
        System.out.println(getClass().getName());
    }
}

3. 初始化各个 case,并指定每个 case 的下一个节点。

String input = "1";
OneCase oneCase = new OneCase("1".equals(input));
TwoCase twoCase = new TwoCase("2".equals(input));
DefaultCase defaultCase = new DefaultCase(true);
oneCase.setNextCase(twoCase);
twoCase.setNextCase(defaultCase);
oneCase.handleRequest();

优化

参考 OkHttp 里面的 Interceptor 实现,将所有的 case 集中起来,通过遍历确定能够处理的 case。
1. 定义一个接口。

interface BaseCase {
    // 所有 case 处理逻辑的方法
    void doSomething(String input, BaseCase baseCase);
}

2. 建立一个责任链管理类,管理所有 case。

public class CaseChain implements BaseCase {
    // 所有 case 列表
    private List<BaseCase> mCaseList = new ArrayList<>();
    // 索引,用于遍历所有 case 列表
    private int            index     = 0;

    // 添加 case
    public CaseChain addBaseCase(BaseCase baseCase) {
        mCaseList.add(baseCase);
        return this;
    }

    @Override
    public void doSomething(String input, BaseCase baseCase) {
        // 所有遍历完了,直接返回
        if (index == mCaseList.size()) return;
        // 获取当前 case
        BaseCase currentCase = mCaseList.get(index);
        // 修改索引值,以便下次回调获取下个节点,达到遍历效果
        index++;
        // 调用当前 case 处理方法
        currentCase.doSomething(input, this);
    }
}

3. 各个 case 实现接口。这里以其中一个为例。

public class OneCase implements BaseCase {
    @Override
    public void doSomething(String input, BaseCase baseCase) {
        if ("1".equals(input)) {
            // TODO do something
            System.out.println(getClass().getName());
            return;
        }
        // 当前没法处理,回调回去,让下一个去处理
        baseCase.doSomething(input, baseCase);
    }
}

4. 初始化各个 case

String input = "1";
CaseChain caseChain = new CaseChain();  
caseChain.addBaseCase(new OneCase())
             .addBaseCase(new TwoCase())
             .addBaseCase(new DefaultCase());  
caseChain.doSomething(input, caseChain);

总结

其实见到该模式就应该能联想到数据结构的链表,所谓的处理就是遍历一遍该列表筛选出符合的就让它去处理即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin-Dev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值