Java设计模式——责任链模式

当一个请求需要在多个对象之间传递,每个对象都可能处理该请求或将其传递给下一个对象。在这种情况下,需要避免将发送者与接收者之间的耦合,以及确定请求的处理方式。此时可使用责任链模式,它的优点有降低耦合度(无需关心哪个对象会处理请求),灵活性(可以动态地改变它们之间的顺序和职责),可扩展性(添加新的处理者,而不会影响现有代码),可维护性(处理者之间职责分开,便于维护);责任链模式也有限制,比如可能导致请求无法被处理或者处理链太长而导致性能问题。

一、抽象类方式实现

假定一个权限认证的例子

java 复制代码
/**
 * 成员类
 */
@Getter
@ToString
public class Member {
    private String loginName;
    private String loginPass;
    @Setter
    private String roleName;

    public Member(String loginName, String loginPass) {
        this.loginName = loginName;
        this.loginPass = loginPass;
    }
}


/**
 * 抽象处理者
 */
public abstract class Handler {
    protected Handler handler;

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

    public abstract void doHandler(Member member);
}


/**
 * 认证处理器
 */
public class AuthHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        if (!"管理员".equals(member.getRoleName())) {
            System.out.println("无操作权限!");
            return;
        }
        System.out.println("操作成功,管理员同志");
    }
}


/**
 * 登陆处理器
 */
public class LoginHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        System.out.println("登陆成功!");
        member.setRoleName("管理员");
        handler.doHandler(member);
    }
}


/**
 * 校验数据处理器
 */
public class ValidDataHandler extends Handler {
    @Override
    public void doHandler(Member member) {
        if (StringUtils.isBlank(member.getLoginName()) || StringUtils.isBlank(member.getLoginPass())) {
            System.out.println("用户名或密码不能为空!");
            return;
        }
        System.out.println("验证通过!");
        handler.doHandler(member);
    }
}


/**
 * 业务服务类
 */
public class MemberService {

    public void login(String loginName, String loginPass) {
        Handler validDateHandler = new ValidDataHandler();
        Handler loginHandler = new LoginHandler();
        Handler authHandler = new AuthHandler();

        validDateHandler.next(loginHandler);
        loginHandler.next(authHandler);

        validDateHandler.doHandler(new Member(loginName, loginPass));
    }

}

编写测试用例

java 复制代码
    /**
     * 责任链模式-权限认证测试
     */
    @Test
    public void testPermission() {
        MemberService memberService = new MemberService();
        memberService.login("admin", "123456");
    }

二、与建造者模式相结合

还是权限认证的例子

java 复制代码
/**
 * 抽象处理者(结合建造者模式)
 */
public abstract class HandlerUp {
    protected HandlerUp handler;

    public void next(HandlerUp handler) {
        this.handler = handler;
    }

    public abstract void doHandler(Member member);

    public static class Builder {
        private HandlerUp head;
        private HandlerUp tail;

        public Builder addHandler(HandlerUp handler) {
            if (this.head == null) {
                this.head = this.tail = handler;
                return this;
            }
            this.tail.next(handler);
            this.tail = handler;

            return this;
        }

        public HandlerUp build() {
            return this.head;
        }
    }
}


/**
 * 认证处理器
 */
public class AuthHandlerUp extends HandlerUp {
    @Override
    public void doHandler(Member member) {
        if (!"管理员".equals(member.getRoleName())) {
            System.out.println("非管理员,无操作权限!");
            return;
        }
        System.out.println("操作成功,管理员同志");
    }
}


/**
 * 登陆处理器
 */
public class LoginHandlerUp extends HandlerUp {
    @Override
    public void doHandler(Member member) {
        System.out.println("登陆成功!");
        member.setRoleName("管理员");
        handler.doHandler(member);
    }
}


/**
 * 校验数据处理器
 */
public class ValidDataHandlerUp extends HandlerUp {
    @Override
    public void doHandler(Member member) {
        if (StringUtils.isBlank(member.getLoginName()) || StringUtils.isBlank(member.getLoginPass())) {
            System.out.println("用户名或密码不能为空!");
            return;
        }
        System.out.println("用户名和密码校验成功!");
        handler.doHandler(member);
    }
}


/**
 * 业务服务类
 */
public class MemberServiceUp {

    public void login(String loginName, String loginPass) {
        new HandlerUp.Builder()
                .addHandler(new ValidDataHandlerUp())
                .addHandler(new LoginHandlerUp())
                .addHandler(new AuthHandlerUp())
                .build()
                .doHandler(new Member(loginName, loginPass));
    }

}

编写测试用例

java 复制代码
    /**
     * 责任链模式-权限认证(增强版)测试
     */
    @Test
    public void testPermissionUp() {
        MemberServiceUp memberServiceUp = new MemberServiceUp();
        memberServiceUp.login("admin", "123456");
    }
相关推荐
Elastic 中国社区官方博客9 分钟前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn18822 分钟前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn1 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su1 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
我命由我123452 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
苜蓿muxu3 小时前
Java 字符串拼接:+、StringBuilder、StringBuffer的区别
java
摇滚侠3 小时前
《Java并发编程之美》第 4 章 Java 并发包中原子操作类原理剖析 阅读笔记 7
java·笔记·python
旋律4144 小时前
同义方法区别(增加类与删除类)
java·后端
学到老活到老4 小时前
方法执行完了,对象为什么还占着内存?
java·jvm