设计模式之职责链模式(卷十三)

在一个系统中,一个请求可以被多个对象所处理,职责链通过类似链表的方式将多个处理对象连接在一起,客户端沿着自定义的顺序传递请求。职责链模式降低了请求的发送端和接收端之间的耦合,使多个对象都有机会处理这个请求

0x00 组成部分

  • Handler:抽象处理者,声明处理请求的方法,同时持有下一个处理者的引用
  • ConcreteHandler:具体处理者,通常有多个,实现了处理请求的方法,也可以选择性的处理部分请求,再传递给下一个处理者继续处理。
  • Client:客户端负责创建具体的链。

架构UML图如下。

0x01 示例代码

package com.kkk.pattern.chain;

/**
 * 官员接口,充当抽象请求处理者。
 * Created by z3jjlzt on 2018/1/11.
 */
public abstract class Official {
    protected Official successor;

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

    //处理请求
    public abstract void handleReq(int level);
}

/**
 * 县令,充当具体处理者。
 * Created by z3jjlzt on 2018/1/11.
 */
public class Magistrate extends Official{

    @Override
    public void handleReq(int level) {
        if (level <= Lawsuit.LEVEL_1) {
            System.out.println("本县令又可以受贿了,好开心!!!");
        } else {
            System.out.println("这么大的案件,我可不敢自己管,感觉交给上司!!!");
            successor.handleReq(level);
        }
    }
}

/**
 * 总督,充当具体处理者。
 * Created by z3jjlzt on 2018/1/11.
 */
public class Governor extends Official {
    @Override
    public void handleReq(int level) {
        if (level <= Lawsuit.LEVEL_2) {
            System.out.println("本总督好想处理大案件啊,可是却天天处理这些个破案件,真浪费了我的才华!!!");
        } else {
            System.out.println("好想自己处理啊,可是我没权利管,好可惜。。。");
            successor.handleReq(level);
        }
    }
}

/**
 * 丞相,充当具体处理者。
 * Created by z3jjlzt on 2018/1/11.
 */
public class PrimeMinister extends Official {
    @Override
    public void handleReq(int level) {
        if (level <= Lawsuit.LEVEL_3) {
            System.out.println("本相今天判他个100年!!!");
        } else {
            System.out.println("泱泱大国可不能毁在我手里呀,感觉通知圣上!!!");
            successor.handleReq(level);
        }
    }
}

/**
 * 皇帝,充当具体处理者。
 * Created by z3jjlzt on 2018/1/11.
 */
public class Emperor extends Official {
    private Random random = new Random();

    //这是个昏君,处理国家大事也看心情。
    private int mood;

    public int getMood() {
        mood = random.nextInt(3);
        return mood;
    }

    @Override
    public void handleReq(int level) {
        switch (getMood()) {
            case 0:
                System.out.println("寡人今日心情欠佳,无心理会朝事");
                break;
            case 1:
                System.out.println("容我看看是谁吃了豹子胆,胆敢当卖国贼!!");
                break;
            default:
                System.out.println("陛下在睡觉!!!");
                break;
        }

    }
}

**
 * 官司分类.
 * Created by z3jjlzt on 2018/1/11.
 */
public class Lawsuit {
    public static final int LEVEL_1 = 1;
    public static final int LEVEL_2 = 2;
    public static final int LEVEL_3 = 3;
    public static final int LEVEL_4 = 4;
}

/**
 * 客户端,负责创建职责链。
 * Created by z3jjlzt on 2018/1/11.
 */
public class Client {
    public static void main(String[] args) {
        Official o1,o2,o3,o4;
        o1 = new Magistrate();
        o2 = new Governor();
        o3 = new PrimeMinister();
        o4 = new Emperor();
        o1.setSuccessor(o2);
        o2.setSuccessor(o3);
        o3.setSuccessor(o4);

        o1.handleReq(1);
        System.out.println();
        o4.handleReq(2);
        System.out.println();
        o3.handleReq(3);
        System.out.println();
        o1.handleReq(4);
        System.out.println();
        o1.handleReq(4);
        System.out.println();
        o1.handleReq(4);
        System.out.println();
        o1.handleReq(4);
    }
}
随机一个结果:
本县令又可以受贿了,好开心!!!

寡人今日心情欠佳,无心理会朝事

本相今天判他个100年!!!

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
容我看看是谁吃了豹子胆,胆敢当卖国贼!!

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
寡人今日心情欠佳,无心理会朝事

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
陛下在睡觉!!!

这么大的案件,我可不敢自己管,感觉交给上司!!!
好想自己处理啊,可是我没权利管,好可惜。。。
泱泱大国可不能毁在我手里呀,感觉通知圣上!!!
寡人今日心情欠佳,无心理会朝事

0xff 总结

  • 优点:无需知道请求具体由哪个处理者处理,新增处理者灵活,符合开闭原则。
  • 缺点:请求不一定会被处理,如果客户端建立职责链不当,会造成死循环。
  • 适用场景:请求的处理者在运行时才确定,在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值