设计模式之责任链模式

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

案例1:

1.需要对一个消息符号,表情,标签处理,有敏感字就不往下执行了,返回已经处理的消息。

package com.zcm.cor;

import lombok.*;
import org.bouncycastle.i18n.filter.*;

import java.util.*;

/**
 * @program: demo
 * @ClassName:Msg
 * @Description:
 * @Author:zcm
 * @Date:2021/2/2 15:44
 */
public class Main {


    public static void main(String[] args) {
        Msg msg = new Msg();
        msg.setMsg("v,v,v 0_0 欢迎大家访问 <baidu.com> 我们都是文明的China人哦,我们都996,699");

        //链条块1
        FilterChain fc1 = new FilterChain();
        fc1.add(new HtmlFilter()).add(new SensitiveFilter());
        //链条块2
        FilterChain fc2 = new FilterChain();
        fc2.add(new FaceFilter()).add(new UrlFilter());
        //将链条块1和链条块2连在一起,形成一条链
        fc1.add(fc2);
        //开始对文本处理
        fc1.doFilter(msg);
        System.out.println("原文:" + msg);
        System.out.println();
        System.out.println("处理后:" + msg.getMsg());
    }

}

@Data
class Msg {
    private String name;
    private String msg;
}

interface Filter {
    Boolean doFilter(Msg msg);
}

/**
 * @Description:替换html尖括号文本
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:31
 */
class HtmlFilter implements Filter {

    @Override
    public Boolean doFilter(Msg msg) {
        String r = msg.getMsg().replace("<", "[").replace(">", "]");
        msg.setMsg(r);
        return true;
    }
}

/**
 * @Description:替换地址
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:31
 */
class UrlFilter implements Filter {

    @Override
    public Boolean doFilter(Msg msg) {
        String r = msg.getMsg().replace("baidu.com", "taobao.com");
        msg.setMsg(r);
        return true;
    }
}

/**
 * @Description:替换敏感数字
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:31
 */
class SensitiveFilter implements Filter {

    @Override
    public Boolean doFilter(Msg msg) {
        String r = msg.getMsg().replace("996", "955");
        msg.setMsg(r);
        return false;
    }
}

/**
 * @Description:将符号替换成表情
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:32
 */
class FaceFilter implements Filter {

    @Override
    public Boolean doFilter(Msg msg) {
        String r = msg.getMsg().replace("v", "QAQ").replace("0_0", "33");
        msg.setMsg(r);
        return true;
    }
}

/**
 * @Description:过滤器
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:32
 */
class FilterChain implements Filter {

    public List<Filter> filters = new ArrayList<>();

    public FilterChain add(Filter filter) {
        filters.add(filter);
        return this;
    }

    @Override
    public Boolean doFilter(Msg msg) {
        for (Filter filter : filters) {
            //如果链条上的一环,有敏感词的 返回失败
            if (!filter.doFilter(msg)) {
                return false;
            }
        }
        return true;
    }
}

2.效果图:案例一主要就是针对消息的一下特殊处理

3.流程图

4.类图 

 

案例2:

对文字处理

package com.zcm.cor.servlet;

import lombok.*;

import java.util.*;

/**
 * @program: demo
 * @ClassName:ServletMain
 * @Description:
 * @Author:zcm
 * @Date:2021/2/3 14:26
 */
public class ServletMain {
    public static void main(String[] args) {
        FilterChain chain = new FilterChain();
        Request request = new Request();
        request.setMsg("你好呀,<baidui.com>,感谢遇见!");

        Response response = new Response();
        chain.add(new HtmlFilter()).add(new UrlFilter());
        chain.doFilter(request, response, chain);
        System.out.println("请求原文:" + request.getMsg());

        System.out.println("响应消息:" + response.getMsg());
    }
}

@Data
class Request {
    private String name;
    private String msg;
}

@Data
class Response {
    private String name;
    private String msg;
}

interface Filter {
    Boolean doFilter(Request request, Response response, FilterChain chain);
}

/**
 * @Description:替换html尖括号文本
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:31
 */
class HtmlFilter implements Filter {

    @Override
    public Boolean doFilter(Request request, Response response, FilterChain chain) {
        String r = request.getMsg().replace("<", "[").replace(">", "]");
        request.setMsg(r);
        StringBuilder builder = new StringBuilder();
        builder.append("-html:").append(r);
        response.setMsg(builder.toString());
        chain.doFilter(request, response, chain);
        return true;
    }
}

/**
 * @Description:替换地址
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:31
 */
class UrlFilter implements Filter {

    @Override
    public Boolean doFilter(Request request, Response response, FilterChain chain) {
        String r = request.getMsg().replace(".com", ".net");
        request.setMsg(r);
        StringBuilder builder = new StringBuilder();

        String s1 = response.getMsg().replaceAll("感谢遇见!", "感谢思念");
        String msg = builder.append(s1).append("-url:").toString();
        String s = msg.replaceAll(request.getMsg(), r);
        response.setMsg(s);

        chain.doFilter(request, response, chain);
        return true;
    }
}

/**
 * @Description:过滤器
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/2 16:32
 */
class FilterChain implements Filter {

    public List<Filter> filters = new ArrayList<>();

    int index = 0;

    public FilterChain add(Filter filter) {
        filters.add(filter);
        return this;
    }

    @Override
    public Boolean doFilter(Request request, Response response, FilterChain chain) {

        if (index == filters.size()) {
            return false;
        }
        //如果链条上的一环,有敏感词的
        Filter filter = filters.get(index);
        index++;
        return filter.doFilter(request, response, chain);
    }
}

2.效果图 :案例二和案例一的区别请求和响应对象独立的

  

 

案例3:模拟客户端请求服务端的过滤器,有点类似Javax.servlet.Filter

1.客户端发送登录请求

2.服务端接收到客户端的请求

3.开始检验客户端的登录请求参数是否正确?

4.服务端校验客户端携带的登录参数异常,开始对客户端做出相对应的响应。

5.客户端接到服务端对自己的回应。

模拟用户登录场景

package com.zcm.cor.servlet.login;

import com.alibaba.fastjson.*;
import lombok.*;
import org.springframework.util.*;

import java.util.*;

/**
 * @program: demo
 * @ClassName:LoginMain
 * @Description:
 * @Author:zcm
 * @Date:2021/2/3 18:00
 */
public class LoginMain {
    public static void main(String[] args) {
        FilterChain chain = new FilterChain()
                .add(new CheckFilter())
                .add(new BlacklistFilter());
        HttpRequest request = new HttpRequest();
        User user = new User();
        user.setUserName("123456");
        user.setPassword("1234156");
        request.setToken(JSON.toJSONString(user));
        HttpResponse response = new HttpResponse();
        chain.doFilter(request, response, chain);
        System.out.println(response.getCode());
        System.out.println(response.getMsg());
    }

}

@Data
class User {
    private String userName;
    private String password;
}

@Data
class HttpRequest {
    private String token;
}

@Data
class HttpResponse {
    private String msg;
    private int code;
}

interface Filter {
    Boolean doFilter(HttpRequest request, HttpResponse response, FilterChain chain);
}

/**
 * @Description:参数检验 1.token携带的参数不可为空
 * 2.账号和密码不可为空
 * 3.账号密码是否正确
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 9:50
 */
class CheckFilter implements Filter {

    @Override
    public Boolean doFilter(HttpRequest request, HttpResponse response, FilterChain chain) {
        if (StringUtils.isEmpty(request.getToken())) {
            response.setCode(500);
            response.setMsg("token令牌不可为空");
            return false;
        }
        JSONObject jsonObject = JSONObject.parseObject(request.getToken());
        String userName = jsonObject.getString("userName");
        String password = jsonObject.getString("password");
        if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)) {
            response.setCode(500);
            response.setMsg("用户名或密码不能为空");
            return false;
        }

        chain.doFilter(request, response, chain);
        return true;
    }
}

/**
 * @Description:黑名单检验 4.该账号是否在黑名单
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 9:54
 */
class BlacklistFilter implements Filter {

    @Override
    public Boolean doFilter(HttpRequest request, HttpResponse response, FilterChain chain) {
        String token = request.getToken();
        JSONObject jsonObject = JSONObject.parseObject(token);
        String userName = jsonObject.getString("userName");
        if (!userName.equals("admin") && !password.equals("123456")) {
            response.setCode(500);
            response.setMsg("用户名或密码错误");
            return false;
        }

        if (userName.equals("admin")) {
            response.setCode(500);
            response.setMsg("此账号被人举报,咱不能登录,请联系客服解封......");
            return false;
        }
        System.out.println("登录成功");
        chain.doFilter(request, response, chain);
        return true;
    }
}

class FilterChain implements Filter {

    public List<Filter> filters = new ArrayList<>();

    int index = 0;

    public FilterChain add(Filter filter) {
        filters.add(filter);
        return this;
    }

    @Override
    public Boolean doFilter(HttpRequest request, HttpResponse response, FilterChain chain) {

        if (index == filters.size()) {
            return false;
        }
        //如果链条上的一环,有敏感词的
        Filter filter = filters.get(index);
        index++;
        return filter.doFilter(request, response, chain);
    }
}






案例4【来自设计模式之禅】:

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

传统写法:

package com.zcm.cor.servlet.advance.tc;

import cn.hutool.core.util.*;

import java.util.*;

/**
 * @program: demo
 * @ClassName:TraditionalClient
 * @Description:
 * @Author:zcm
 * @Date:2021/2/4 16:44
 */
public class TraditionalClient {
    public static void main(String[] args) {
        List<IWomen> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new Women(RandomUtil.randomInt(1,4), "我要去逛街~"));
        }
        
        IHandler fatherHandler = new FatherHandler();
        IHandler husbandHandler = new HusbandHandler();
        IHandler sonHandler = new SonHandler();
        for (IWomen iWomen : list) {
            switch (iWomen.getType()) {
                case 1:
                    fatherHandler.getResponse(iWomen);
                    break;
                case 2:
                    husbandHandler.getResponse(iWomen);
                    break;
                case 3:
                    sonHandler.getResponse(iWomen);
                    break;
            }
        }
    }


}

/**
 * @program: demo
 * @ClassName:Handler
 * @Description:
 * @Author:zcm
 * @Date:2021/2/4 10:54
 */
interface IHandler {
    /**
     * @Description:做出响应
     * @Author: zcm
     * @Version:v.2.7.1
     * @Date:2021/2/4 11:05
     */
    void getResponse(IWomen women);
}

/**
 * @Description:女人
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 10:58
 */
interface IWomen {
    /**
     * @Description:类型 1.未婚 2.结婚 3.守寡
     * @Author: zcm
     * @Version:v.2.7.1
     * @Date:2021/2/4 10:57
     */
    public int getType();

    /**
     * @Description:请求
     * @Author: zcm
     * @Version:v.2.7.1
     * @Date:2021/2/4 10:57
     */
    public String getRequest();
}

class Women implements IWomen {
    //默认:未婚
    private int type = 1;
    //请求信息
    private String request;

    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }

    public Women(int type, String request) {
        this.type = type;
        switch (this.type) {
            case 1:
                this.request = "女儿的请求:" + request;
                break;
            case 1:
                this.request = "妻子的请求:" + request;
                break;
            case 2:
                this.request = "母亲的请求:" + request;
                break;

        }
    }
}

/**
 * @Description:向父亲请示
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 11:18
 */
class FatherHandler implements IHandler {
    @Override
    public void getResponse(IWomen women) {
        System.out.println("----------------向父亲请示-----------------------");
        System.out.println(women.getRequest());
        System.out.println("父亲回答:同意");
    }
}

/**
 * @Description:向丈夫请示
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 11:18
 */
class HusbandHandler implements IHandler {

    @Override
    public void getResponse(IWomen women) {
        System.out.println("----------------向丈夫请示-----------------------");
        System.out.println(women.getRequest());
        System.out.println("丈夫回答:不同意");
    }
}

/**
 * @Description:向儿子请示
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 11:18
 */
class SonHandler implements IHandler {

    @Override
    public void getResponse(IWomen women) {
        System.out.println("----------------向儿子请示-----------------------");
        System.out.println(women.getRequest());
        System.out.println("儿子回答:同意");
    }
}

耦合过重,违反了迪米特原则,异常情况没考虑,失去了面向对象的意义。既然有这么多的问题,那我们要想办法来解决这些问题,我们可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去了,那就由儿子来处理这个请求。

 父亲、丈夫、儿子每个节点有两个选择:要么做出回应;要么把请求转发到后序环节。 

责任链的写法 

package com.zcm.cor.servlet.advance;
import java.util.*;

/**
 * @program: demo
 * @ClassName:Main
 * @Description:
 * @Author:zcm
 * @Date:2021/2/4 11:27
 */
public class Main {
    public static void main(String[] args) {
        List<IWomen> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            list.add(new Women(new Random().nextInt(3), "我要去逛街~"));
        }
        IHandler fatherHandler = new FatherHandler();
        IHandler husbandHandler = new HusbandHandler();
        IHandler sonHandler = new SonHandler();
        fatherHandler.setNext(husbandHandler);
        husbandHandler.setNext(sonHandler);
        for (IWomen iWomen : list) {
            fatherHandler.handlerMessage(iWomen);
        }
    }

}

/**
 * @program: demo
 * @ClassName:Handler
 * @Description:
 * @Author:zcm
 * @Date:2021/2/4 10:54
 */
abstract class IHandler {
    private int level = 0;
    private IHandler nextHandler;

    public IHandler(int level) {
        this.level = level;
    }

    /**
     * @Description:做出响应
     * @Author: zcm
     * @Version:v.2.7.1
     * @Date:2021/2/4 11:05
     */
    abstract void getResponse(IWomen women);

    final void handlerMessage(IWomen women) {
        if (women.getType() == this.level) {
            this.getResponse(women);
        } else {
            if (this.nextHandler != null) {  //有后续环节,才把请求往后递送    
                this.nextHandler.handlerMessage(women);

            } else { //已经没有后续处理人了,不用处理了    
                System.out.println("-----------没地方请示了,不做处理!---------\n");
            }
        }
    }

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

/**
 * @Description:女人
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 10:58
 */
interface IWomen {
    /**
     * @Description:类型 1.未婚 2.结婚 3.守寡
     * @Author: zcm
     * @Version:v.2.7.1
     * @Date:2021/2/4 10:57
     */
    public int getType();

    /**
     * @Description:请求
     * @Author: zcm
     * @Version:v.2.7.1
     * @Date:2021/2/4 10:57
     */
    public String getRequest();
}

class Women implements IWomen {
    //默认:未婚
    private int type = 1;
    //请求信息
    private String request;

    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public String getRequest() {
        return this.request;
    }

    public Women(int type, String request) {
        this.type = type;
        switch (this.type) {
            case 0:
                this.request = "女儿的请求:" + request;
                break;
            case 1:
                this.request = "妻子的请求:" + request;
                break;
            case 2:
                this.request = "母亲的请求:" + request;
                break;

        }
    }
}

/**
 * @Description:向父亲请示
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 11:18
 */
class FatherHandler extends IHandler {

    public FatherHandler() {
        super(0);
    }

    @Override
    public void getResponse(IWomen women) {
        System.out.println("----------------向父亲请示-----------------------");
        System.out.println(women.getRequest());
        System.out.println("父亲回答:同意");
    }
}

/**
 * @Description:向丈夫请示
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 11:18
 */
class HusbandHandler extends IHandler {

    public HusbandHandler() {
        super(1);
    }

    @Override
    public void getResponse(IWomen women) {
        System.out.println("----------------向丈夫请示-----------------------");
        System.out.println(women.getRequest());
        System.out.println("丈夫回答:不同意");
    }
}

/**
 * @Description:向儿子请示
 * @Author: zcm
 * @Version:v.2.7.1
 * @Date:2021/2/4 11:18
 */
class SonHandler extends IHandler {
    //儿子只处理母亲的请求
    public SonHandler() {
        super(2);
    }

    @Override
    public void getResponse(IWomen women) {
        System.out.println("----------------向儿子请示-----------------------");
        System.out.println(women.getRequest());
        System.out.println("儿子回答:同意");
    }
}

总结:

优点:

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

缺点:

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

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值