程序员必知!责任链模式的实战应用与案例分析

发布时间:2024年01月06日

程序员必知!责任链模式的实战应用与案例分析 - 程序员古德

责任链模式让多个对象依次处理请求,降低发送者和接收者的耦合度,以在线购物为例,用户提交订单需经多步验证,通过责任链模式,验证器按顺序处理请求,先用户身份,再支付方式,最后配送地址,任一验证失败即停止流程并反馈错误,责任链模式提升了代码的灵活性和可扩展性。

定义

程序员必知!责任链模式的实战应用与案例分析 - 程序员古德

责任链模式是一种行为设计模式,它使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,这些对象形成一个处理请求的链,client只需要将请求发送到链头即可。举一个业务中的例子:假设有一个在线购物网站,用户可以在网站上浏览商品并购买,在用户提交订单时,需要验证用户的身份、支付方式、配送地址等信息,可以使用责任链模式来处理这个流程,假设有以下验证器:

  1. 用户身份验证器:验证用户的身份信息是否正确。
  2. 支付方式验证器:验证用户的支付方式是否可用。
  3. 配送地址验证器:验证用户的配送地址是否有效。

可以将这些验证器组成一个责任链,并让它们依次处理请求,当用户提交订单时,责任链模式的第一个验证器(用户身份验证器)会首先处理请求,如果身份信息验证通过,它会将请求传递给下一个验证器(支付方式验证器),如果支付方式验证通过,再传递给下一个验证器(配送地址验证器),如果任何一个验证器不通过,整个流程就会停止,并返回相应的错误信息给用户。这样,就可以避免将请求发送者和接收者之间的耦合关系,使得代码更加灵活和可扩展。

代码案例

程序员必知!责任链模式的实战应用与案例分析 - 程序员古德

在未使用责任链模式的情况下,可能会将多个处理逻辑放在一个方法中,或者在一个方法中依次调用多个处理方法,这种方式会导致代码的可维护性和可扩展性降低,因为当需要添加或修改处理逻辑时,必须修改这个方法,下面是一个未使用责任链模式的反例代码:

// 订单验证类,未使用责任链模式  
public class OrderValidator {  
  
    // 验证用户身份  
    private boolean validateUser(User user) {  
        // 模拟验证逻辑  
        return user != null && user.isAuthenticated();  
    }  
  
    // 验证支付方式  
    private boolean validatePayment(Payment payment) {  
        // 模拟验证逻辑  
        return payment != null && payment.isAvailable();  
    }  
  
    // 验证配送地址  
    private boolean validateAddress(Address address) {  
        // 模拟验证逻辑  
        return address != null && address.isValid();  
    }  
  
    // 提交订单方法,包含所有验证逻辑  
    public String submitOrder(User user, Payment payment, Address address) {  
        if (!validateUser(user)) {  
            return "用户身份验证失败!";  
        }  
        if (!validatePayment(payment)) {  
            return "支付方式验证失败!";  
        }  
        if (!validateAddress(address)) {  
            return "配送地址验证失败!";  
        }  
        // 所有验证通过,处理订单  
        return "订单提交成功!";  
    }  
}  
  
// 客户端调用案例  
public class Client {  
    public static void main(String[] args) {  
        OrderValidator validator = new OrderValidator();  
          
        // 创建用户、支付方式和配送地址对象  
        User user = new User(); // 假设已经认证  
        Payment payment = new Payment(); // 假设可用  
        Address address = new Address(); // 假设有效  
  
        // 提交订单并打印结果  
        String result = validator.submitOrder(user, payment, address);  
        System.out.println(result); // 输出:订单提交成功!  
  
        // 尝试使用无效的用户提交订单  
        User invalidUser = null; // 无效用户  
        String invalidUserResult = validator.submitOrder(invalidUser, payment, address);  
        System.out.println(invalidUserResult); // 输出:用户身份验证失败!  
    }  
}  
  
// 假设存在的其他类  
class User {  
    public boolean isAuthenticated() {  
        // 模拟认证逻辑  
        return true;  
    }  
}  
  
class Payment {  
    public boolean isAvailable() {  
        // 模拟支付方式可用逻辑  
        return true;  
    }  
}  
  
class Address {  
    public boolean isValid() {  
        // 模拟地址验证逻辑  
        return true;  
    }  
}

在上面的代码中,OrderValidator 类负责处理订单提交前的所有验证逻辑,submitOrder 方法中依次调用了用户验证、支付方式验证和配送地址验证方法,如果任何一个验证失败,方法都会立即返回错误信息,只有当所有验证都通过时,才会返回成功信息。

client代码创建了一个订单验证器实例,并尝试使用不同的用户提交订单,第一次提交使用有效用户,因此成功,第二次提交使用无效用户(null),因此失败,并返回相应的错误信息。

这种方式的问题是,如果需要添加新的验证逻辑(比如库存验证),必须修改 submitOrder 方法,这违反了开闭原则(对扩展开放,对修改关闭),此外,如果验证逻辑变得复杂,submitOrder 方法会变得非常庞大和难以维护。

当使用责任链模式时,可以创建一个处理请求的链,每个链上的节点都有机会处理该请求,如果某个节点能够处理请求,则处理它并可能结束链的进一步处理,否则,它将请求传递给链上的下一个节点,以下是一个使用了责任链模式的正例代码实现:

// 抽象处理者角色  
abstract class Handler {  
    protected Handler successor; // 下一个处理者  
  
    public void setSuccessor(Handler successor) {  
        this.successor = successor;  
    }  
  
    public abstract void handleRequest(Request request); // 处理请求的抽象方法  
}  
  
// 具体处理者角色A - 用户验证  
class UserHandler extends Handler {  
    @Override  
    public void handleRequest(Request request) {  
        if (request instanceof UserRequest) {  
            UserRequest userRequest = (UserRequest) request;  
            if (userRequest.getUser() != null && userRequest.getUser().isAuthenticated()) {  
                System.out.println("用户验证通过!");  
            } else {  
                System.out.println("用户验证失败!");  
                return; // 验证失败,不再传递请求  
            }  
        }  
        // 如果本处理者处理后请求未被结束,则继续传递  
        if (successor != null) {  
            successor.handleRequest(request);  
        }  
    }  
}  
  
// 具体处理者角色B - 支付验证  
class PaymentHandler extends Handler {  
    @Override  
    public void handleRequest(Request request) {  
        if (request instanceof PaymentRequest) {  
            PaymentRequest paymentRequest = (PaymentRequest) request;  
            if (paymentRequest.getPayment() != null && paymentRequest.getPayment().isAvailable()) {  
                System.out.println("支付验证通过!");  
            } else {  
                System.out.println("支付验证失败!");  
                return; // 验证失败,不再传递请求  
            }  
        }  
        // 如果本处理者处理后请求未被结束,则继续传递  
        if (successor != null) {  
            successor.handleRequest(request);  
        }  
    }  
}  
  
// 具体处理者角色C - 地址验证  
class AddressHandler extends Handler {  
    @Override  
    public void handleRequest(Request request) {  
        if (request instanceof AddressRequest) {  
            AddressRequest addressRequest = (AddressRequest) request;  
            if (addressRequest.getAddress() != null && addressRequest.getAddress().isValid()) {  
                System.out.println("地址验证通过!");  
            } else {  
                System.out.println("地址验证失败!");  
                return; // 验证失败,不再传递请求  
            }  
        }  
        // 正常情况下,这里可以处理请求或结束处理,但为了示例简单性,不在这里做任何额外处理  
    }  
}  
  
// 请求接口  
interface Request {  
}  
  
// 用户请求  
class UserRequest implements Request {  
    private User user;  
  
    public UserRequest(User user) {  
        this.user = user;  
    }  
  
    public User getUser() {  
        return user;  
    }  
}  
  
// 支付请求  
class PaymentRequest implements Request {  
    private Payment payment;  
  
    public PaymentRequest(Payment payment) {  
        this.payment = payment;  
    }  
  
    public Payment getPayment() {  
        return payment;  
    }  
}  
  
// 地址请求  
class AddressRequest implements Request {  
    private Address address;  
  
    public AddressRequest(Address address) {  
        this.address = address;  
    }  
  
    public Address getAddress() {  
        return address;  
    }  
}  
  
// 用户类  
class User {  
    private boolean authenticated;  
  
    public User(boolean authenticated) {  
        this.authenticated = authenticated;  
    }  
  
    public boolean isAuthenticated() {  
        return authenticated;  
    }  
}  
  
// 支付类  
class Payment {  
    private boolean available;  
  
    public Payment(boolean available) {  
        this.available = available;  
    }  
  
    public boolean isAvailable() {  
        return available;  
    }  
}  
  
// 地址类  
class Address {  
    private boolean valid;  
  
    public Address(boolean valid) {  
        this.valid = valid;  
    }  
  
    public boolean isValid() {  
        return valid;  
    }  
}  
  
// 客户端调用案例  
public class Client {  
    public static void main(String[] args) {  
        // 创建责任链  
        Handler userHandler = new UserHandler();  
        Handler paymentHandler = new PaymentHandler();  
        Handler addressHandler = new AddressHandler();  
        userHandler.setSuccessor(paymentHandler);  
        paymentHandler.setSuccessor(addressHandler);  
  
        // 创建请求并发送给责任链  
        User user = new User(true);  
        Payment payment = new Payment(true);  
        Address address = new Address(true);  
  
        // 发送用户请求  
        userHandler.handleRequest(new UserRequest(user));  
  
        // 发送支付请求  
        userHandler.handleRequest(new PaymentRequest(payment));  
  
        // 发送地址请求  
        userHandler.handleRequest(new AddressRequest(address));  
  
        // 尝试使用无效用户发送请求  
        User invalidUser = new User(false);  
        userHandler.handleRequest(new UserRequest(invalidUser));  
    }  
}

在上述代码中,创建了三个具体处理者(UserHandler, PaymentHandler, AddressHandler),它们分别处理用户验证、支付验证和地址验证,每个处理者都实现了抽象处理者Handler定义的接口,并且可以在处理请求时将请求传递给链中的下一个处理者。

在client中创建了一个责任链,每个请求都被传递给链中的适当处理者,如果处理者能够处理该请求,则处理它,否则将其传递给下一个处理者,当客户端尝试使用无效用户发送请求时,用户验证处理者会捕获这个条件并输出错误消息,同时停止请求的进一步处理。

核心总结

程序员必知!责任链模式的实战应用与案例分析 - 程序员古德

责任链模式是一种行为设计模式,它允许对象对请求进行处理,或者将其传递给链中的下一个处理者,这种模式可以消除请求的发送者和接收者之间的耦合,它如下特点:

优点

  1. 降低耦合度:请求者不需要知道具体是哪个对象处理了请求,只需将请求发送到链上即可。
  2. 灵活性高:通过改变链内的成员或调整它们的顺序,可以动态地新增或删除责任。
  3. 明确各职责:每个处理者都清楚自己的职责,只处理自己感兴趣或能处理的请求。

缺点

  1. 请求可能得不到处理:如果链上的所有处理者都不处理请求,请求可能会直接结束,没有明确的反馈。
  2. 性能问题:对于长链或复杂处理,可能会导致处理时间增长,影响性能。
  3. 调试困难:由于请求可能在多个处理者之间传递,当出现问题时,定位问题可能会比较困难。

使用建议

  1. 在明确各处理者职责和处理顺序的情况下使用。
  2. 避免过长的责任链,以减少性能损失和调试难度。
  3. 当请求可能得不到处理时,应有相应的反馈或默认处理机制。

完!

关注我,每天学习互联网编程技术 - 程序员古德

文章来源:https://blog.csdn.net/qusikao/article/details/135432606
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。