开发模式学习之路手机移动程序开发Android知识

浅谈Android移动架构(五)行为模式之责任链模式

2017-01-03  本文已影响192人  轻轻笑声

#######定义:
使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系,将这些对象形成一条链,并沿着这条链传递该请求,直到有对象处理它为止.
#######重点:
上一个处理对象必须含有下一个处理对象的引用,形成一个单向链表.
#######使用场景:
一个请求可以被多个处理者处理或处理者未明确指定时.


UML类图.png

#######模式的简单实现
场景:一个程序员出差要向领导申请出差费用,不同级别的领导有不等费用的审批权力.
1.首先定义一个程序员类:

/**
 * 程序猿类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class ProgramApe {
    private int expenses;// 声明整型成员变量表示出差费用
    private String apply = "爹要点钱出差";// 声明字符串型成员变量表示差旅申请

    /*
     * 含参构造方法
     */
    public ProgramApe(int expenses) {
        this.expenses = expenses;
    }

    /*
     * 获取程序员具体的差旅费用
     */
    public int getExpenses() {
        return expenses;
    }

    /*
     * 获取差旅费申请
     */
    public String getApply() {
        return apply;
    }
}

2.然后依次是各个领导类:

/**
 * 小组长类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class GroupLeader {

    /**
     * 处理请求
     * 
     * @param ape
     *            具体的猿
     */
    public void handleRequest(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("GroupLeader: Of course Yes!");
    }
}
/**
 * 项目主管类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Director {
    /**
     * 处理请求
     * 
     * @param ape
     *            具体的猿
     */
    public void handleRequest(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("Director: Of course Yes!");
    }
}
/**
 * 部门经理类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Manager {
    /**
     * 处理请求
     * 
     * @param ape
     *            具体的猿
     */
    public void handleRequest(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("Manager: Of course Yes!");
    }
}
/**
 * 老总类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Boss {
    /**
     * 处理请求
     * 
     * @param ape
     *            具体的猿
     */
    public void handleRequest(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("Boss: Of course Yes!");
    }
}

3.场景实现

/**
 * 场景模拟类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Client {
    public static void main(String[] args) {
        /*
         * 先来一个程序猿 这里给他一个三万以内的随机值表示需要申请的差旅费
         */
        ProgramApe ape = new ProgramApe((int) (Math.random() * 30000));

        /*
         * 再来四个老大
         */
        GroupLeader leader = new GroupLeader();
        Director director = new Director();
        Manager manager = new Manager();
        Boss boss = new Boss();

        /*
         * 处理申请
         */
        if (ape.getExpenses() <= 1000) {
            leader.handleRequest(ape);
        } else if (ape.getExpenses() <= 5000) {
            director.handleRequest(ape);
        } else if (ape.getExpenses() <= 10000) {
            manager.handleRequest(ape);
        } else {
            boss.handleRequest(ape);
        }
    }
}

上面的代码虽然在一定程度上体现了责任链模式的思想,但是不好,耦合度太高了,很明显所有的领导都有共同的handleRequest方法而程序猿也有不同类型的,比如一个公司的PHP,c/c++,Android,iOS等等,所有的这些共性我们都可以将其抽象为一个抽象类或接口,比如我们的程序猿抽象父类:
#######下面对上面代码进行改造:
1.首先定义一个程序员抽象类

/**
 * 程序猿抽象接口
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public abstract class ProgramApes {
    /**
     * 获取程序员具体的差旅费用
     * 
     * @return 要多少钱
     */
    public abstract int getExpenses();

    /**
     * 获取差旅费申请
     * 
     * @return Just a request
     */
    public abstract String getApply();
}

2.这时我们就可以实现该接口具现化一个具体的程序猿,比如Android猿:

/**
 * Android程序猿类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class AndroidApe extends ProgramApes {
    private int expenses;// 声明整型成员变量表示出差费用
    private String apply = "爹要点钱出差";// 声明字符串型成员变量表示差旅申请

    /*
     * 含参构造方法
     */
    public AndroidApe(int expenses) {
        this.expenses = expenses;
    }

    @Override
    public int getExpenses() {
        return expenses;
    }

    @Override
    public String getApply() {
        return apply;
    }
}
同样的,所有的老大都有一个批复经费申请的权利,我们把这个权利抽象为一个IPower接口:

/**
 * 老大们的权利接口
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public interface IPower {
    /**
     * 处理请求
     * 
     * @param ape
     *            具体的猿
     */
    public void handleRequest(ProgramApe ape);
}

3.把所有领导抽象为一个leader抽象类,在该抽象类中实现处理逻辑:

/**
 * 领导抽象类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public abstract class Leader {
    private int expenses;// 当前领导能批复的金额
    private Leader mSuperiorLeader;// 上级领导

    /**
     * 含参构造方法
     * 
     * @param expenses
     *            当前领导能批复的金额
     */
    public Leader(int expenses) {
        this.expenses = expenses;
    }

    /**
     * 回应程序猿
     * 
     * @param ape
     *            具体的程序猿
     */
    protected abstract void reply(ProgramApe ape);

    /**
     * 处理请求
     * 
     * @param ape
     *            具体的程序猿
     */
    public void handleRequest(ProgramApe ape) {
        /*
         * 如果说程序猿申请的money在当前领导的批复范围内
         */
        if (ape.getExpenses() <= expenses) {
            // 那么就由当前领导批复即可
            reply(ape);
        } else {
            /*
             * 否则看看当前领导有木有上级
             */
            if (null != mSuperiorLeader) {
                // 有的话简单撒直接扔给上级处理即可
                mSuperiorLeader.handleRequest(ape);
            } else {
                // 没有上级的话就批复不了老……不过在这个场景中总会有领导批复的淡定
                System.out.println("Goodbye my money......");
            }
        }
    }

    /**
     * 为当前领导设置一个上级领导
     * 
     * @param superiorLeader
     *            上级领导
     */
    public void setLeader(Leader superiorLeader) {
        this.mSuperiorLeader = superiorLeader;
    }
}

4.这么一来,我们的领导老大们就有了实实在在的权利职责去处理底层苦逼程序猿的请求。OK,接下来要做的事就是让所有的领导继承该类:

/**
 * 小组长类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class GroupLeader extends Leader {

    public GroupLeader() {
        super(1000);
    }

    @Override
    protected void reply(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("GroupLeader: Of course Yes!");
    }
}
/**
 * 项目主管类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Director extends Leader{
    public Director() {
        super(5000);
    }

    @Override
    protected void reply(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("Director: Of course Yes!");     
    }
}
/**
 * 部门经理类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Manager extends Leader {
    public Manager() {
        super(10000);
    }

    @Override
    protected void reply(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("Manager: Of course Yes!");
    }
}
/**
 * 老总类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Boss extends Leader {
    public Boss() {
        super(40000);
    }

    @Override
    protected void reply(ProgramApe ape) {
        System.out.println(ape.getApply());
        System.out.println("Boss: Of course Yes!");
    }
}

5.场景再现:

/**
 * 场景模拟类
 * 
 * @author Aige{@link https://github.com/AigeStudio}
 *
 */
public class Client {
    public static void main(String[] args) {
        /*
         * 先来一个程序猿 这里给他一个三万以内的随机值表示需要申请的差旅费
         */
        ProgramApe ape = new ProgramApe((int) (Math.random() * 30000));

        /*
         * 再来四个老大
         */
        Leader leader = new GroupLeader();
        Leader director = new Director();
        Leader manager = new Manager();
        Leader boss = new Boss();

        /*
         * 设置老大的上一个老大
         */
        leader.setLeader(director);
        director.setLeader(manager);
        manager.setLeader(boss);

        // 处理申请
        leader.handleRequest(ape);
    }
}

#######对以上代码总结:
OK,这样我们就将请求和处理分离开来,对于程序猿来说,不需要知道是谁给他批复的钱,而对于领导们来说,也不需要确切地知道是批给哪个程序猿,只要根据自己的责任做出处理即可,由此将两者优雅地解耦。
#######Android源码:
Android中关于责任链模式比较明显的体现就是在事件分发过程中对事件的投递,其实严格来说,事件投递的模式并不是严格的责任链模式,但是其是责任链模式的一种变种体现.这里就不多讲了.
#######最终总结:
优点:
可以对请求者和处理者关系的解耦提高代码的灵活性,比如上面我们的例子中如果在主管和经理之间多了一个总监,那么总监可以批复小于7500的经费,这时候根据我们上面重构的模式,仅需新建一个总监类继承Leader即可其它所有的存在类都可保持不变.
缺点:
是对链中责任人的遍历,如果责任人太多那么遍历必定会影响性能,特别是在一些递归调用中,要慎重.

后续继续更新,敬请期待......

上一篇下一篇

猜你喜欢

热点阅读