【Java设计模式】 Java设计模式之(五)责任链模式(Chain of Responsibility Pattern)

本文目录

一、责任链模式介绍

二、代码实现

2.1 业务逻辑

2.2 代码实现


顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。

在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。

一、责任链模式介绍

意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。

主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。

何时使用:在处理消息的时候以过滤很多道。

如何解决:拦截的类都实现统一接口。

关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。

应用实例: 1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。

优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。

缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。

使用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。

注意事项:在 JAVA WEB 中遇到很多应用。

二、代码实现

所有设计模式的代码实现例子都可在码云上查看哦,感兴趣的可以查看哈,码云地址:https://gitee.com/no8g/java-design-patterns

2.1 业务逻辑

中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父、既嫁从夫、夫死从子”,也就是说一个女性,在没有结婚的时候要听从于父亲,结了婚后听从于丈夫,丈夫死了还要听儿子的。举个例子来说,一个女的要出去逛街,同样这样的一个请求,在她没有出嫁前她必须征得父亲的同意,出嫁之后必须获得丈夫的许可,那丈夫死了怎么办?一般都是男的比女的死的早,还要问问儿子是否允许自己出去逛街,估计你下边马上要问要是没有儿子怎么办?请示小叔子、侄子等等。在父系社会中,妇女只占从属地位,现在想想中国的妇女还是比较悲惨的,逛个街还要请示来请示去,而且作为父亲、丈夫、儿子只有两种选择:要不承担起责任来告诉她允许或不允许逛街,要不就让她请示下一个人,这是整个社会体系的约束。

应用到我们项目中就是业务规则,那我们来看怎么把“三从”通过我们的程序来实现,需求很简单:通过程序描述一下古代妇女的“三从”制度,好我们先看类图:

我们可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去天国报道了,那就由儿子来处理这个请求,类似于这样请求:

父亲、丈夫、儿子每个节点有两个选择:要么承担责任,做出回复;要么把请求转发到后序环节。结构分析的已经很清楚了,那我们看怎么来实现这个功能,先看类图:

从类图上看,三个实现类 Father、Husband、Son 只要实现构造函数和父类的中抽象方法就可以了,具体怎么处理这些请求,都已经转移到了 Hanlder 抽象类中,我们来看 Hanlder 怎么实现:

结果也正确,业务调用类 Client 也不用去做判断到底是需要谁去处理,而且 Handler 抽象类的子类以后可以继续增加下去,只是我们这个传递链增加而已,调用类可以不用了解变化过程,甚至是谁在处理这个请求都不用知道。

以上讲解的就是责任链模式,你看 Father、Husband、Son 这三个类的处理女性的请求时是不是在传递呀,每个环节只有两个选项:要么承担责任做出回应,要么向下传递请求,最终会有环节做出回应,通用类图如下:

2.2 代码实现

package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;

import com.iot.practice.designpattern.chainofresponsibility.IWomen;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * <p>Client 此类用于:</p>
 * <p>@author:hujm</p>
 * <p>@date:2021年02月19日 11:37</p>
 * <p>@remark:</p>
 */
public class ChainOfResponsibilityClient {

    public static void main(String[] args) {
        // 随机挑选几个女性
        Random random = new Random();
        List<IWomen> iWomenList = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            iWomenList.add(new IWomenImpl(random.nextInt(4), "我要看电影"));
        }

        // 定义三个请示对象
        Handler father = new Father();
        Handler husband = new Husband();
        Handler son = new Son();

        // 设置请示顺序
        father.setNext(husband);
        husband.setNext(son);

        for (IWomen iWomen : iWomenList) {
            father.HandleMessage(iWomen);
        }
    }
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;

import com.iot.practice.designpattern.chainofresponsibility.IWomen;

/**
 * <p>Handler 此类用于:</p>
 * <p>@author:hujm</p>
 * <p>@date:2021年02月19日 10:56</p>
 * <p>@remark:
 * 有没有看到,其实在这里也用到模版方法模式,在模版方法中判断请求的级别和当前能够处理的级别,
 * 如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,由下一环节做出回应。基本方
 * 法 response 要各个实现类都要实现,我们来看三个实现类:
 * </p>
 */
public abstract class Handler {

    /**
     * 能处理的级别
     */
    private int level = 0;

    /**
     * 责任传递,下一个人责任人是谁
     */
    private Handler nextHandler;

    /**
     * 构造函数:每个类都要说明一下自己能处理哪些请求
     *
     * @param level 能处理的级别
     */
    public Handler(int level) {
        this.level = level;
    }

    /**
     * 一个女性(女儿,妻子或者是母亲)要求逛街,你要处理这个请求
     *
     * @param iWomen 女性统称
     */
    public final void HandleMessage(IWomen iWomen) {
        if (iWomen.getType() == this.level) {
            this.response(iWomen);
        } else {
            // 有后续环节,才把请求往后递送
            if (this.nextHandler != null) {
                this.nextHandler.HandleMessage(iWomen);
            } else {
                // /已经没有后续处理人了,不用处理了
                System.out.println("-----------没地方请示了,不做处理!---------\n");
            }
        }
    }

    /**
     * 如果不属于你处理的返回,你应该让她找下一个环节的人,比如
     * 女儿出嫁了,还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示
     *
     * @param handler 处理类
     */
    public void setNext(Handler handler) {
        this.nextHandler = handler;
    }

    /**
     * 有请示那当然要回应
     *
     * @param iWomen 女性统称
     */
    public abstract void response(IWomen iWomen);
}
package com.iot.practice.designpattern.chainofresponsibility;

/**
 * <p>IWomen 此接口用于:</p>
 * <p>@author:hujm</p>
 * <p>@date:2021年02月19日 9:55</p>
 * <p>@remark:古代悲哀女性的总称</p>
 */
public interface IWomen {

    /**
     * 获得个人状况
     *
     * @return 个人状况数值
     */
    public int getType();

    /**
     * 获得个人请示,你要干什么?出去逛街?约会?还是看电影
     *
     * @return 干什么
     */
    public String getRequest();
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;

import com.iot.practice.designpattern.chainofresponsibility.IWomen;

/**
 * <p>IWomenImpl 此类用于:</p>
 * <p>@author:hujm</p>
 * <p>@date:2021年02月19日 11:23</p>
 * <p>@remark:</p>
 */
public class IWomenImpl implements IWomen {

    /**
     * 通过一个int类型的参数来描述妇女的个人状况
     * 1---未出嫁
     * 2---出嫁
     * 3---夫死
     */
    private int type = 0;

    /**
     * 妇女的请示
     */
    private String request = "";

    /**
     * 构造函数传递过来请求
     *
     * @param type    个人状况
     * @param request 妇女的请示
     */
    public IWomenImpl(int type, String request) {
        this.type = type;
        this.request = request;
        // 为了显示好看点,我在这里做了点处理
        switch(this.type) {
            case 1:
                this.request = "女儿的请求是:" + request;
                break;
            case 2:
                this.request = "妻子的请求是:" + request;
                break;
            case 3:
                this.request = "母亲的请求是:" + request;
                break;
        }
    }

    /**
     * 获得自己的状况
     *
     * @return 自己的状况
     */
    @Override
    public int getType() {
        return this.type;
    }

    /**
     * 获得妇女的请求
     *
     * @return 妇女的请求
     */
    @Override
    public String getRequest() {
        return this.request;
    }
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;

import com.iot.practice.designpattern.chainofresponsibility.IWomen;

/**
 * <p>Father 此类用于:</p>
 * <p>@author:hujm</p>
 * <p>@date:2021年02月19日 11:13</p>
 * <p>@remark:</p>
 */
public class Father extends Handler {

    /**
     * 父亲只处理女儿的请求
     */
    public Father() {
        super(1);
    }

    /**
     * 父亲的答复
     *
     * @param iWomen 女性统称
     */
    @Override
    public void response(IWomen iWomen) {
        System.out.println("--------女儿向父亲请示-------");
        System.out.println(iWomen.getRequest());
        System.out.println("父亲的答复是:同意\n");
    }
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;

import com.iot.practice.designpattern.chainofresponsibility.IWomen;

/**
 * <p>Husband 此类用于:</p>
 * <p>@author:hujm</p>
 * <p>@date:2021年02月19日 11:15</p>
 * <p>@remark:</p>
 */
public class Husband extends Handler {

    /**
     * 丈夫只处理妻子的请求
     */
    public Husband() {
        super(2);
    }

    /**
     * 丈夫的答复
     *
     * @param iWomen 女性统称
     */
    @Override
    public void response(IWomen iWomen) {
        System.out.println("--------妻子向丈夫请示-------");
        System.out.println(iWomen.getRequest());
        System.out.println("丈夫的答复是:同意\n");
    }
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;

import com.iot.practice.designpattern.chainofresponsibility.IWomen;

/**
 * <p>Son 此类用于:</p>
 * <p>@author:hujm</p>
 * <p>@date:2021年02月19日 11:18</p>
 * <p>@remark:</p>
 */
public class Son extends Handler {

    /**
     * 儿子只处理母亲的请求
     */
    public Son() {
        super(3);
    }

    /**
     * 儿子的答复
     *
     * @param iWomen 女性统称
     */
    @Override
    public void response(IWomen iWomen) {
        System.out.println("--------母亲向儿子请示-------");
        System.out.println(iWomen.getRequest());
        System.out.println("儿子的答复是:同意\n");
    }
}

完结!

猜你喜欢

转载自blog.csdn.net/weixin_44299027/article/details/113885752
今日推荐