Android常用设计模式-责任链模式

617 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

Android中的责任链模式

责任链模式又叫拦截器模式,在Android源码与第三方库都有广泛的应用。

比如OkHttp的拦截器模式,比如View事件的分发,ViewGroup事件投递的递归调用就类似于一条责任链,一旦其寻找到责任者,那么将由责任者持有并消费掉该次事件,具体体现在View的onTouchEvent方法中返回值的设置,如果返回false,那么意味着当前的View不会是该次的责任人,将不会对其持有;如果返回true,此时View会持有该事件并不再向外传递。

责任链模式是指,当一个请求经过一个对象,就询问当前对象是否进行处理和拦截,判断是否可以往下一个对象传递,这样形成一个链,每一个对象都有机会处理改请求。

我们定义一个拦截请求,定义一个拦截器处理请求,再定义每一个拦截对象

1.拦截器请求接口

public abstract class InterceptChain<T> {

    public InterceptChain next;

    public void intercept(T data) {
        if (next != null) {
            next.intercept(data);
        }
    }

}

2.拦截器处理器

public class InterceptChainHandler<T> {

    InterceptChain _interceptFirst;

    public void add(InterceptChain interceptChain) {
        if (_interceptFirst == null) {
            _interceptFirst = interceptChain;
            return;
        }

        InterceptChain node = _interceptFirst;

        while (true) {
            if (node.next == null) {
                node.next = interceptChain;
                break;
            }
            node = node.next;
        }
    }

    public void intercept(T data) {
        _interceptFirst.intercept(data);
    }

}

3.通过对象来判断是否需要拦截

public class DialogPass {

    public String msg;
    public int passType;

}

4.定义每一个拦截对象,这里来5个


   class OneIntercept : InterceptChain<DialogPass>() {

        override fun intercept(data: DialogPass?) {
            if (data != null) {
                val interceptData = "当前的Data1:${data.msg}"
                YYLogUtils.w(interceptData)

                //判断当前是否弹窗
                if (data.passType == 1) {
                    FangIOSDialog(mActivity).apply {
                        setTitle("测试弹框1")
                        setMessage("弹框的内容")
                        setNegativeButton("No") {
                            dismiss()
                        }
                        setPositiveButton("Yes") {
                            dismiss()
                            //判断逻辑,是否需要弹出下一个弹窗
                            //如果需要弹出下一个弹窗 设置下一个弹窗的passType
                            data.passType = 2
                            super.intercept(data)
                        }
                        show()
                    }
                }else{
                    super.intercept(data)
                }
            } else {
                super.intercept(data)
            }
        }
    }

     class TwoIntercept : InterceptChain<DialogPass>() {

        override fun intercept(data: DialogPass?) {
            if (data != null) {
                val interceptData = "当前的Data2:${data.msg}"
                YYLogUtils.w(interceptData)

                //判断当前是否弹窗
                if (data.passType == 2) {
                    FangIOSDialog(mActivity).apply {
                        setTitle("测试弹框2")
                        setMessage("弹框的内容")
                        setNegativeButton("No") {
                            dismiss()
                        }
                        setPositiveButton("Yes") {
                            dismiss()
                            //判断逻辑,是否需要弹出下一个弹窗
                            //如果需要弹出下一个弹窗 设置下一个弹窗的passType
                            data.passType = 3
                            super.intercept(data)
                        }
                        show()
                    }
                }else{
                    super.intercept(data)
                }
            } else {
                super.intercept(data)
            }
        }
    }

     class ThreeIntercept : InterceptChain<DialogPass>() {

        override fun intercept(data: DialogPass?) {
            if (data != null) {
                val interceptData = "当前的Data3:${data.msg}"
                YYLogUtils.w(interceptData)

                //判断当前是否弹窗
                if (data.passType == 3) {
                    FangIOSDialog(mActivity).apply {
                        setTitle("测试弹框3")
                        setMessage("弹框的内容")
                        setNegativeButton("No") {
                            dismiss()
                        }
                        setPositiveButton("Yes") {
                            dismiss()
                            //判断逻辑,是否需要弹出下一个弹窗
                            //如果需要弹出下一个弹窗 设置下一个弹窗的passType
                            data.passType = 5
                            super.intercept(data)
                        }
                        show()
                    }
                }else{
                    super.intercept(data)
                }
            } else {
                super.intercept(data)
            }
        }

    }

     class FourIntercept : InterceptChain<DialogPass>() {

        override fun intercept(data: DialogPass?) {
            if (data != null) {
                val interceptData = "当前的Data4:${data.msg}"
                YYLogUtils.w(interceptData)

                //判断当前是否弹窗
                if (data.passType == 4) {
                    FangIOSDialog(mActivity).apply {
                        setTitle("测试弹框4")
                        setMessage("弹框的内容")
                        setNegativeButton("No") {
                            dismiss()
                        }
                        setPositiveButton("Yes") {
                            dismiss()
                            //判断逻辑,是否需要弹出下一个弹窗
                            //如果需要弹出下一个弹窗 设置下一个弹窗的passType
                            data.passType = 5
                            super.intercept(data)
                        }
                        show()
                    }
                }else{
                    super.intercept(data)
                }
            } else {
                super.intercept(data)
            }
        }

    }

     class FiveIntercept : InterceptChain<DialogPass>() {

        override fun intercept(data: DialogPass?) {
            if (data != null) {
                val interceptData = "当前的Data5:${data.msg}"
                YYLogUtils.w(interceptData)

                //判断当前是否弹窗
                if (data.passType == 5) {
                    FangIOSDialog(mActivity).apply {
                        setTitle("测试弹框5")
                        setMessage("弹框的内容")
                        setNegativeButton("No") {
                            dismiss()
                        }
                        setPositiveButton("Yes") {
                            dismiss()
                            //判断逻辑,是否需要弹出下一个弹窗
                            //如果需要弹出下一个弹窗 设置下一个弹窗的passType
                        }
                        show()
                    }
                }else{
                    super.intercept(data)
                }
            } else {
                super.intercept(data)
            }
        }

测试使用


        //测试拦截器模式
        val intercepts = InterceptChainHandler<DialogPass>()

        intercepts.add(OneIntercept())
        intercepts.add(TwoIntercept())
        intercepts.add(ThreeIntercept())
        intercepts.add(FourIntercept())
        intercepts.add(FiveIntercept())

        val dialogPass = DialogPass().apply {
            msg = "测试弹窗流程"
            passType = 1
        }
        intercepts.intercept(dialogPass)

总结

责任链设计模式并没有固定的写法,可以有不同的实现,中心思想都是一样的,就是从一个起点发起请求,然后沿着任务链依次传递给每一个节点上的对象,直到有一个节点处理这个请求为止,也是我们再平常开发中常用的设计模式之一了。

优点:
可以对请求者和处理者的关系解耦,提高代码的灵活性。

缺点:
每次都需要对链中请求处理者遍历,如果处理者太多那么遍历必定会影响性能,特别是在一些递归调用者中,要慎用。

此篇只是展示责任链模式的概念与基本使用,关于弹窗的拦截后期会单独出一期实战的文章。