java/android 设计模式学习笔记(15)---责任链模式

  这篇博客我们来介绍一下责任链模式(Chain-of-responsibility Pattern),责任联模式又称为职责链模式,是行为型设计模式之一。顾名思义,责任链模式中存在一个链式结构,多个节点首尾相连,每个节点都可以被拆开再连接,因此,链式结构具有很好的灵活性。将这样一种结构应用于编程领域,将每一个节点看作是一个对象,每一个对象拥有不同的处理逻辑,将一个请求从链式的首段发出,沿着链的路径依次传递给每一个节点对象,直至有对象处理这个请求为止,这就是责任链或者职责链的通俗定义。
  转载请注明出处:http://blog.csdn.net/self_study/article/details/52012370
  PS:对技术感兴趣的同鞋加群544645972一起交流。

设计模式总目录

  java/android 设计模式学习笔记目录

特点

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

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

UML类图

  责任链模式的 uml 图如下所示:
  这里写图片描述
责任链模式有两大角色:

  • Handler:抽象处理者角色,声明一个请求处理的方法,并在其中保持对下一个处理节点 Hanlder 对象的引用;
  • ConcreteHandler:
  • 具体处理者角色,对请求进行处理,如果不能处理则将该请求转发给下一个节点上的处理对象。
对于请求 Request 来说,在大多数情况下,责任链中的请求和对应的处理规则是不尽相同的,在这种情况下可以将请求进行封装,同时对请求的处理规则也进行封装作为一个独立的对象,如上图所示。据此可以写出通用代码,首先是 Handler 角色:
AbstractHandler.class

public abstract class AbstractHandler {
    protected AbstractHandler nextHandler;

    public final void handleRequest(AbstractRequest request) {
        if (getHandlerLevel() == request.getLevel()) {
            handle(request);
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(request);
            } else {
                System.out.print("there is no handler that can handle this request");
            }
        }
    }

    protected abstract int getHandlerLevel();

    protected abstract void handle(AbstractRequest request);
}

ConcreteHandler1.class

public class ConcreteHandler1 extends AbstractHandler{
    @Override
    protected int getHandlerLevel() {
        return 1;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.print("ConcreteHandler1 handle this request : " + request.getContent() + "\n");
    }
}

ConcreteHandler2.class

public class ConcreteHandler2 extends AbstractHandler{
    @Override
    protected int getHandlerLevel() {
        return 2;
    }

    @Override
    protected void handle(AbstractRequest request) {
        System.out.print("ConcreteHandler2 handle this request : " + request.getContent() + "\n");
    }
}

然后是请求角色:
AbstractRequest.class

public abstract class AbstractRequest {

    private Object object;

    public AbstractRequest(Object object) {
        this.object = object;
    }

    public Object getContent() {
        return object;
    }

    public abstract int getLevel();
}

ConcreteRequest1.class

public class ConcreteRequest1 extends AbstractRequest{

    public ConcreteRequest1(Object object) {
        super(object);
    }

    @Override
    public int getLevel() {
        return 1;
    }
}

ConcreteRequest2.class

public class ConcreteRequest2 extends AbstractRequest{

    public ConcreteRequest2(Object object) {
        super(object);
    }

    @Override
    public int getLevel() {
        return 2;
    }
}

最后客户端测试代码:

public class Client {
    public static void main(String[] args) {
        AbstractHandler handler1 = new ConcreteHandler1();
        AbstractHandler handler2 = new ConcreteHandler2();
        handler1.nextHandler = handler2;

        AbstractRequest request1 = new ConcreteRequest1("request1");
        AbstractRequest request2 = new ConcreteRequest2("request2");

        handler1.handleRequest(request1);
        handler1.handleRequest(request2);
    }
}

结果如下:
这里写图片描述

示例与源码

  其实责任链模式在实际项目过程中遇到的非常多,Android 和 Java 源码也一样,举几个简单的例子:

  1. ViewGroup 和 View 中 touch 事件的分发,子 View 的 onTouchEvent 返回 true 代码消费该事件并不再传递,false 代表不消费并且传递到父 ViewGroup 去处理,这些树形结构的子 View 就是责任链上一个个处理对象;
  2. OrderedBroadcast,广播的每一个接收者按照优先级依次接受消息,如果处理完成之后可以调用 abortBroadcast 终止广播,不是自己处理的就可以传递给下一个处理者;
  3. try-catch语句,每一个 catch 根据 Exception 类型进行匹配,形成一个责任链,如果有一个 catch 语句与该 Exception 符合,这个 Exception 就交由给它进行处理,之后所有 catch 语句都不会再次执行。

  我们这就以 wiki 上的代码为例:每个人都有一个支出审批的额度,超过审批额度之后将会传递给下一个审批人,直到最后:
审批人相关类

public abstract class PurchasePower {
    protected static final double BASE = 500;
    protected PurchasePower successor;

    abstract protected double getAllowable();
    abstract protected String getRole();

    public void setSuccessor(PurchasePower successor) {
        this.successor = successor;
    }

    public void processRequest(PurchaseRequest request){
        if (request.getAmount() < this.getAllowable()) {
            System.out.println(this.getRole() + " will approve $" + request.getAmount());
        } else if (successor != null) {
            successor.processRequest(request);
        }
    }
}
public class ManagerPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*10;
    }

    protected String getRole(){
        return "Manager";
    }
}

public class DirectorPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*20;
    }

    protected String getRole(){
        return "Director";
    }
}

public class VicePresidentPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*40;
    }

    protected String getRole(){
        return "Vice President";
    }
}

public class PresidentPPower extends PurchasePower {

    protected int getAllowable(){
        return BASE*60;
    }

    protected String getRole(){
        return "President";
    }
}

审批类

public class PurchaseRequest {
    private double amount;
    private String purpose;

    public PurchaseRequest(double amount, String purpose) {
        this.amount = amount;
        this.purpose = purpose;
    }

    public double getAmount() {
        return amount;
    }
    public void setAmount(double amt)  {
        amount = amt;
    }

    public String getPurpose() {
        return purpose;
    }
    public void setPurpose(String reason) {
        purpose = reason;
    }
}

最后是客户端的测试代码:

public class CheckAuthority {
    public static void main(String[] args) {
        ManagerPPower manager = new ManagerPPower();
        DirectorPPower director = new DirectorPPower();
        VicePresidentPPower vp = new VicePresidentPPower();
        PresidentPPower president = new PresidentPPower();
        manager.setSuccessor(director);
        director.setSuccessor(vp);
        vp.setSuccessor(president);

        // Press Ctrl+C to end.
        try {
            while (true) {
                System.out.println("Enter the amount to check who should approve your expenditure.");
                System.out.print(">");
                double d = Double.parseDouble(new BufferedReader(new InputStreamReader(System.in)).readLine());
                manager.processRequest(new PurchaseRequest(d, "General"));
           }
        } catch(Exception e) {
            System.exit(1);
        }
    }
}

代码简洁明了,都应该能看懂。

总结

  责任链模式的优点显而易见,可以对请求者和处理者关系解耦,提高代码的灵活性,通过改变链内的成员或调动他们的次序,允许你动态地新增或者删除职责;但是责任链模式最大的缺点在于对链中请求处理者的遍历,如果处理者太多那么必定会影响性能,特别是在一些递归调用中,而且不容易观察运行时的特征,有碍于除错。
  很多资料中会介绍纯和不纯的责任链模式,在标准的责任链模式中,责任链上的一个节点只允许有两个行为:处理或者推给下个节点处理,而不允许处理完之后又推给下个节点,前者被很多资料称为纯的责任链模式,而后者被称为不纯的责任链模式。其实在实际的系统里,纯的责任链很难找到。如果坚持责任链不纯便不是责任链模式,那么责任链模式便不会有太大意义了。

源码下载

  https://github.com/zhaozepeng/Design-Patterns/tree/master/ChainOfResponsibilityPattern

引用

https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
http://blog.csdn.net/jason0539/article/details/45091639

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

GeekBand第十一周笔记 - 2016-07-25 17:07:19

本周的主要内容介绍Gradle,NDK,管理依赖和Git等 一、Gradle Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。 面向Java应用为主。当前其支持的语言限于Java、Groovy和Scala,计划未来将支持更多的语言。 Coding只是软件开发中的一个部分 编译源代码 运行单元测试和集成测试 执行静态代码分析,生成分析报告 创建分布版本 部署到目标环
在安卓开发中,谷歌已经为我们提供了许多原生控件,基本上能够满足我们日常的开发需求,但是某些项目中原生控件可能达不到产品所要求的各式各样的酷炫效果或功能效果,这个时候我们只能自己自定义控件来满足项目需求,我们知道自定义控件包括三种方式: 1继承控件,即继承谷歌提供的原生控件,在此基础上提供一些原生控件不具备的功能,如github上各种酷炫效果的开源组件基本上都是采用的这种方式. 2组合控件:即组合多个原生控件来达到某些单个原生控件原本不具备的功能,这个在日常开发中应该是使用的比较多的,如基本上每个App都存

Android多点触摸交互处理 - 2016-07-25 17:07:15

安卓手机中,多点触摸是是最基本的操作,下面就使用程序进行演示多点触摸操作 一、获取触摸事件中的点击,移动和抬起事件,创建新的安卓项目,如下面代码所示,分别为MainActivity类代码和Layout布局文件,用于实现获取点击事件 1.1、MainActivity类中代码,代码中为布局对象root添加监听事件,使用switch进行对屏幕时间进行判断,用于判断事件的按下还是移动,在代码中      root=(RelativeLayout) findViewById(R.id.content);用于绑定布局
内容是博主照着书敲出来的,博主码字挺辛苦的,转载请注明出处,后序内容陆续会码出。 前言:ListView——列表,它作为一个非常重要的显示方式,不管是在Web中还是移动平台中,都是一个非常好的、不开或缺的展示信息的工具。在Android中,ListView控件接管了这一重担,在大量的场合下,我们都需要使用这个控件。虽然在Android 5.X时代,RecyclerView在很多地方都在逐渐取代ListView,但ListView的使用范围依然非常的广泛,它这万年老大哥的地位也不是轻易就能撼动的。下面就介绍
Android ListView使用简介 ListView 是 Android 软件开发中十分常用也十分重要的一个 UI 控件。 ListView 的每一个子项可以是一个简单的字符串,也可以是一组 View 的组合,开发者完全可以根据自己的需求来定义显示的形式。 如何使用一个 ListView 实现对数据的显示呢 ? 1. 创建 ListView 控件,已备数据显示 2. 准备要显示的数据 3. 为 ListView 构建一个数据适配器 (Adapter) 4. 绑定适配器 5. 处理 ListView
转载请标明出处: 一片枫叶的专栏 文本我们将讲解android studio打包apk,aar,jar包的相关知识。apk包就是android系统的安装包,这里没什么好说的,aar包是android中独有的类库包,而jar包是java中特有的类库包,在具体的介绍打包之前,我们先来aar包和jar包的区别。 jar包与aar包的区别 jar是java字节码文件(class文件)的归档文件,其不包含android中的资源文件等信息; aar是android中特有的归档文件,既包含字节码文件也包含android
欢迎转载,转载请注明出处: http://blog.csdn.net/dmk877/article/details/51980734 在上一篇文章中,我们详细讨论了Tween动画的xml的实现以及interpolator的使用,相信通过上篇文章大家对Tween动画的xml属性的配置会有一个详细的理解,当然这篇文章也是承接上篇文章,所以强烈建议先阅读上篇文章: Android开发之Tween(补间动画)完全解析(上) ,这篇文章将从代码的角度实现上篇文章的效果。 如有疑问请留言,如有谬误欢迎批评指正。 Tw

Android闹钟设置的解决方案 - 2016-07-25 14:07:00

Android设置闹钟并不像IOS那样这么简单,做过Android设置闹钟的开发者都知道里面的坑有多深。下面记录一下,我解决Android闹钟设置的解决方案。 主要问题 API19开始AlarmManager的机制修改。 应用程序被Kill掉后,设置的闹钟不响。 6.0以上进入Doze模式会使JobScheduler停止工作。 手机设置重启后,闹钟失效问题。 API19以上AlarmManager机制的修改 API19之前AlarmManager提供了三个设置闹钟的方法,由于业务需求闹钟只需要一次性,所以
start_kernel之前的汇编代码建立了内核临时页表,完成了内核区域的静态线性映射,保证内核可以在舒适的虚拟地址空间(运行地址和链接地址一致)运行。进入start_kernel之后就要准备建立完整的页表映射,这部分工作是在paging_init中完成。 不过在建立完整页表映射之前还需要进行一些准备工作,本文来分析下。 为了简化整个代码流程,便于分析,我的设备内核配置为不使用高端内存,不配置CONFIG_HIGHMEM。bootargs中传给内核的mem=256. 内核版本号:3.4.55 paging

App的打磨之路(下) - 2016-07-25 14:07:48

前言:该文接上两篇博文 App的打磨之路(上) 和 App的打磨之路(中) ,继续描述打包、反编译及加固。 一、打包 每个Android应用在完成后都需要打成APK包,对于单个打包的方式在此就不赘述了,基本IDE都带,只是在对外发布的应用需要配置属于该应用的唯一签名,下文主要讲述需要上传多个市场的情况下怎么批量打包。 1、Maven打包 Maven是一个项目管理工具,它包含了一个项目对象模型(Project Object Model),一组标准集合,一个项目生命周期(ProjectLifecycle),一