设计模式(六)——责任链模式

问题提出

在生活中,经常遇到这样的问题。例如:在企业中,员工请假的问题。假设假期少于一天,可由组长决定;少于两天的,可由车间主任决定;大于两天的,由经理决定。组长、主任、经理构成了一条功能链。员工逐级向上进行申请,直到获得授权。再比如生产产品,需要经过多道工序。

解决以上这些问题,责任链模式是一个较好的选择。

责任链模式

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

适用的情景如下:

  • 有许多对象可以处理用户的请求,应用程序可以自动确定谁处理用户请求。
  • 希望用户在不必明确指定接收者的情况下,向多个接收者提交一个请求,
  • 程序希望动态定制可处理用户请求的对象集合。

责任链模式中涉及的角色如下:

  • 抽象处理者(Handler):定义一个处理请求的抽象类。可以定义一个方法,以设定和返回下一个节点的引用。
  • 具体处理者(ConcreteHandler):具体处理者在接收到请求之后可以选择将请求处理完毕,或者将请求传递给下一个节点。
  • 客户(Client):负责形成具体处理者的功能链,并传递初始的请求。

简单实现

请求类,day为请假的天数。

public class Request {
    public int day;

    public Request(int day) {
        this.day = day;
    }
}

抽象处理者类

public abstract class Handler {
    private Handler next;

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }

    public abstract boolean handle(Request req);
}

三个具体的处理者类,组长

public class ZuZhang extends Handler{
    static int limit = 1;

    @Override
    public boolean handle(Request req) {
        if (req.day <= limit){
            System.out.println("ZuZhang agree the request!");
            return true;
        }
        return getNext().handle(req);
    }
}

主任

public class ZhuRen extends Handler {
    static int limit = 2;

    @Override
    public boolean handle(Request req) {
        if (req.day <= limit){
            System.out.println("ZhuRen agree the request!");
            return true;
        }
        return getNext().handle(req);
    }
}

经理

public class JingLi extends Handler{
    @Override
    public boolean handle(Request req) {
        System.out.println("JingLi agree the request!");
        return true;
    }
}

客户类,生成责任链的前后顺序关系。

public class Chain {
    private Handler one = new ZuZhang();
    private Handler two = new ZhuRen();
    private Handler three = new JingLi();

    public void createChain(){
        one.setNext(two);
        two.setNext(three);
    }

    public void handle(Request req){
        one.handle(req);
    }
}

简单测试类

public class Test {
    public static void main(String[] args) {
        Request req = new Request(2);
        Chain c = new Chain();
        c.createChain();
        c.handle(req);
    }
}

加入反射

上述代码中,Chain构建的责任链是刚性的,若需求发生了变化,链中需增加或删除节点。解决这个问题,可采取配置文件+反射的方式。

定义config.properties中的格式为:

chain=ZuZhang,ZhuRen,JingLi

Chain2

public class Chain2 {
    private Handler handler[];

    public void createChain() {
        try {
            String path = "路径\\config.properties";
            FileInputStream in = new FileInputStream(path);
            Properties p = new Properties();
            p.load(in);
            String s = p.getProperty("chain");
            String unit[] = s.split(",");
            int n = unit.length;
            handler = new Handler[n];
            for (int i = 0; i < n; i++) {
                handler[i] = (Handler) Class.forName(unit[i]).newInstance();
            }
            for (int i = 0; i < n - 1; i++) {
                handler[i].setNext(handler[i + 1]);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void handle(Request req) {
        handler[0].handle(req);
    }
}

回调技术

回调就是类对象方法间相互调用的技术。例如:

public class A {
    public void fA(){
        System.out.println("This is A::fA()");
        B obj = new B();
        obj.fB(this);
    }

    public void fA2(){
        System.out.println("This is A::fA2()");
    }

    public static void main(String[] args) {
        new A().fA();
    }
}
public class B {
    public void fB(A obj){
        System.out.println("This is B::fB()");
        obj.fA2();
    }
}

利用回调技术,也可以实现责任链模式的功能代码。

应用示例

对英文字符串数据进行如下处理:

  • 全部变为大写字母
  • 去掉所有空格

例如“I am a student”,经处理后变为“IAMASTUDENT”。代码如下:

定义抽象处理者接口Filter

public interface Filter {
    void doFilter(Request req, Response rep,FilterChain fc);
}

请求类

public class Request {
    String req;

    public Request(String req) {
        this.req = req;
    }
}

响应类

public class Response {
    String rep;

    public Response(String rep) {
        this.rep = rep;
    }
}

两个具体处理类,小写变大写

public class UpperFilter implements Filter {
    @Override
    public void doFilter(Request req, Response rep, FilterChain fc) {
        String s = req.req;
        rep.rep = s.toUpperCase();
        fc.doFilter(req, rep, fc);
    }
}

去除空格

public class BlankFilter implements Filter {
    @Override
    public void doFilter(Request req, Response rep, FilterChain fc) {
        String s = rep.rep;
        StringBuffer sbuf = new StringBuffer();
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch != ' ') {
                sbuf.append(ch);
            }
        }
        rep.rep = sbuf.toString();
        fc.doFilter(req, rep, fc);
    }
}

实现回调功能,生成过滤集合。

public class FilterChain implements Filter {
    ArrayList<Filter> ary = new ArrayList<>();
    int index = 0;

    void addFilter(Filter f) {
        ary.add(f);
    }

    @Override
    public void doFilter(Request req, Response rep, FilterChain fc) {
        if (index == ary.size()) {
            return;
        }
        Filter f = ary.get(index);
        index++;
        f.doFilter(req, rep, fc);
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        Request req = new Request("i am a student");
        Response rep = new Response("");
        Filter upperFilter = new UpperFilter();
        Filter blankFilter = new BlankFilter();
        FilterChain fc = new FilterChain();
        fc.addFilter(upperFilter);
        fc.addFilter(blankFilter);
        fc.doFilter(req, rep, fc);
        System.out.println(rep.rep);
    }
}

上述代码doFilter方法的实现是同步的,若请求处理时间很长,则程序无法执行其他功能。

异步调用

可采用多线程技术实现异步调用。

FilterChain实现异步回调

public class FilterChain {
    ArrayList<Filter> ary = new ArrayList<>();

    int index = 0;

    public void addFilter(Filter f){
        ary.add(f);
    }

    public void doFilter(Request req,Response rep,FilterChain fc){
        if (index == ary.size()){
            return;
        }
        Filter f = ary.get(index);
        index++;
        MyThread th = new MyThread(req,rep,f,fc);
        th.start();
    }
}

封装req、rep、f、fc

public class MyThread extends Thread {
    Request req;
    Response rep;
    Filter f;
    FilterChain fc;

    public MyThread(Request req, Response rep, Filter f, FilterChain fc) {
        this.req = req;
        this.rep = rep;
        this.f = f;
        this.fc = fc;
    }

    @Override
    public void run() {
        f.doFilter(req, rep, fc);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值