设计模式之责任链模式

1. 概念

责任链设计模式是一种行为设计模式,它允许你创建一个对象链。请求从链的一端进入,并沿着链的路径依次经过各个对象,直至找到合适的处理者。每个对象都决定是否要处理该请求或将其传递给链中的下一个对象。

1.1 核心概念

  • Handler(处理者):每个处理者对象包含了处理请求的代码。处理者通常定义一个处理方法来执行请求处理,并决定是否将请求传递给下一个处理者。

  • 链(Chain):处理者按照某种方式连接在一起,构成一个处理链。请求进入链的一端,并沿着链传递直至有一个处理者处理请求或者请求到达链的末端。

  • Request(请求):请求是要被处理的对象。每个处理者检查请求并进行处理,或将其传递给下一个处理者。

1.2 工作原理

  • 当一个请求进入责任链时,它被传递给第一个处理者。
  • 处理者决定是否处理请求,如果能处理则执行相应操作,如果不能处理则将请求传递给链中的下一个处理者。
  • 这个过程会持续直到有一个处理者能够处理请求或者请求到达链的末端。

1.3 优势

  • 松散耦合:责任链模式允许你添加或修改处理者而无需修改现有代码。
  • 动态设置链:你可以动态设置处理链,在运行时指定处理者的顺序或者数量。

1.4 示例

举个例子,假设有一个报销审批系统。不同级别的员工有不同的报销限额。责任链模式可以用来构建审批流程,每个处理者代表一个管理层级,根据报销金额来决定是否批准请求。如果一个处理者无法批准请求,则将请求传递给下一个处理者,直到得到最终的审批结果。

责任链模式在很多场景下都有应用,特别是处理流程连续、需要灵活调整处理顺序的场景。

2. 举例

2.1 简单的购买审批场景

当使用责任链模式时,我们可以考虑一个简单的购买审批场景。不同级别的员工有不同的审批权限,低级别员工的审批额度小,而高级别员工有更高的审批额度。如果一个员工无法批准请求,请求将被传递给下一个更高级别的员工。

以下是一个使用Java实现责任链模式的示例:

java 复制代码
// 定义请求类
class PurchaseRequest {
    private double amount;

    public PurchaseRequest(double amount) {
        this.amount = amount;
    }

    public double getAmount() {
        return amount;
    }
}

// 定义处理者接口
interface Approver {
    void setNext(Approver next);
    void processRequest(PurchaseRequest request);
}

// 具体处理者实现
class Manager implements Approver {
    private Approver next;
    private double approvalLimit = 1000;

    @Override
    public void setNext(Approver next) {
        this.next = next;
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() <= approvalLimit) {
            System.out.println("Manager approved the request of amount: " + request.getAmount());
        } else if (next != null) {
            next.processRequest(request);
        }
    }
}

class Director implements Approver {
    private Approver next;
    private double approvalLimit = 5000;

    @Override
    public void setNext(Approver next) {
        this.next = next;
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() <= approvalLimit) {
            System.out.println("Director approved the request of amount: " + request.getAmount());
        } else if (next != null) {
            next.processRequest(request);
        }
    }
}

class President implements Approver {
    private double approvalLimit = 10000;

    @Override
    public void setNext(Approver next) {
        // President is the final authority, doesn't need a next
    }

    @Override
    public void processRequest(PurchaseRequest request) {
        if (request.getAmount() <= approvalLimit) {
            System.out.println("President approved the request of amount: " + request.getAmount());
        } else {
            System.out.println("Request requires higher approval.");
        }
    }
}

// 使用责任链模式
public class ChainOfResponsibilityExample {
    public static void main(String[] args) {
        Approver manager = new Manager();
        Approver director = new Director();
        Approver president = new President();

        // 构建责任链
        manager.setNext(director);
        director.setNext(president);

        // 发起请求
        PurchaseRequest request1 = new PurchaseRequest(500);
        manager.processRequest(request1);

        PurchaseRequest request2 = new PurchaseRequest(2500);
        manager.processRequest(request2);

        PurchaseRequest request3 = new PurchaseRequest(15000);
        manager.processRequest(request3);
    }
}

这个例子中,我们创建了不同级别的处理者(Manager、Director、President),并设置了它们的审批额度。然后我们建立了一个责任链,通过调用 processRequest 方法来处理不同额度的购买请求。请求会从低级别的员工一直传递到更高级别的员工,直到找到能够批准请求的员工。

2.2 在线文件处理系统

我们可以想象一个在线文件处理系统。不同类型的文件需要经过不同的处理器进行处理,如图片文件、文本文件、视频文件等。每个处理器能够处理特定类型的文件,如果一个处理器无法处理该类型文件,请求将被传递给下一个处理器。

下面是一个使用责任链模式处理文件的简单示例:

java 复制代码
// 文件处理请求
class File {
    private String fileName;
    private String fileType;

    public File(String fileName, String fileType) {
        this.fileName = fileName;
        this.fileType = fileType;
    }

    public String getFileName() {
        return fileName;
    }

    public String getFileType() {
        return fileType;
    }
}

// 文件处理器接口
interface FileHandler {
    void setNext(FileHandler next);
    void handleFile(File file);
}

// 图片文件处理器
class ImageHandler implements FileHandler {
    private FileHandler next;

    @Override
    public void setNext(FileHandler next) {
        this.next = next;
    }

    @Override
    public void handleFile(File file) {
        if (file.getFileType().equals("image")) {
            System.out.println("ImageHandler: Processing image file - " + file.getFileName());
        } else if (next != null) {
            next.handleFile(file);
        }
    }
}

// 文本文件处理器
class TextHandler implements FileHandler {
    private FileHandler next;

    @Override
    public void setNext(FileHandler next) {
        this.next = next;
    }

    @Override
    public void handleFile(File file) {
        if (file.getFileType().equals("text")) {
            System.out.println("TextHandler: Processing text file - " + file.getFileName());
        } else if (next != null) {
            next.handleFile(file);
        }
    }
}

// 视频文件处理器
class VideoHandler implements FileHandler {
    @Override
    public void setNext(FileHandler next) {
        // VideoHandler is the final handler and does not require a next handler
    }

    @Override
    public void handleFile(File file) {
        if (file.getFileType().equals("video")) {
            System.out.println("VideoHandler: Processing video file - " + file.getFileName());
        } else {
            System.out.println("No handler found for the file: " + file.getFileName());
        }
    }
}

// 使用责任链模式处理文件
public class FileHandlerExample {
    public static void main(String[] args) {
        FileHandler imageHandler = new ImageHandler();
        FileHandler textHandler = new TextHandler();
        FileHandler videoHandler = new VideoHandler();

        // 构建处理链
        imageHandler.setNext(textHandler);
        textHandler.setNext(videoHandler);

        // 发起文件处理请求
        File file1 = new File("image1.jpg", "image");
        imageHandler.handleFile(file1);

        File file2 = new File("document.txt", "text");
        imageHandler.handleFile(file2);

        File file3 = new File("video.mp4", "video");
        imageHandler.handleFile(file3);

        File file4 = new File("music.mp3", "audio");
        imageHandler.handleFile(file4);
    }
}

在这个示例中,不同类型的文件经过责任链,每个处理器(ImageHandler、TextHandler、VideoHandler)能够处理特定类型的文件。文件请求会从低级别处理器传递到更高级别处理器,直到找到能够处理该类型文件的处理器,或者请求到达责任链的末端。

2.3 简单的餐厅点餐系统

让我们考虑一个简单的餐厅点餐系统的场景。假设不同类型的菜品由不同的厨师来负责制作,而服务员负责接收顾客的点餐请求并将其传递给合适的厨师。

下面是使用责任链模式模拟餐厅点餐系统的示例:

java 复制代码
// 餐品订单
class Order {
    private String dishName;
    private String category;

    public Order(String dishName, String category) {
        this.dishName = dishName;
        this.category = category;
    }

    public String getDishName() {
        return dishName;
    }

    public String getCategory() {
        return category;
    }
}

// 厨师接口
interface Chef {
    void setNextChef(Chef nextChef);
    void handleOrder(Order order);
}

// 中餐厨师
class ChineseChef implements Chef {
    private Chef nextChef;

    @Override
    public void setNextChef(Chef nextChef) {
        this.nextChef = nextChef;
    }

    @Override
    public void handleOrder(Order order) {
        if (order.getCategory().equalsIgnoreCase("Chinese")) {
            System.out.println("Chinese Chef is preparing " + order.getDishName());
        } else if (nextChef != null) {
            nextChef.handleOrder(order);
        }
    }
}

// 西餐厨师
class WesternChef implements Chef {
    private Chef nextChef;

    @Override
    public void setNextChef(Chef nextChef) {
        this.nextChef = nextChef;
    }

    @Override
    public void handleOrder(Order order) {
        if (order.getCategory().equalsIgnoreCase("Western")) {
            System.out.println("Western Chef is preparing " + order.getDishName());
        } else if (nextChef != null) {
            nextChef.handleOrder(order);
        }
    }
}

// 甜点厨师
class DessertChef implements Chef {
    @Override
    public void setNextChef(Chef nextChef) {
        // DessertChef is the final chef and does not require a next chef
    }

    @Override
    public void handleOrder(Order order) {
        if (order.getCategory().equalsIgnoreCase("Dessert")) {
            System.out.println("Dessert Chef is preparing " + order.getDishName());
        } else {
            System.out.println("No chef found for " + order.getDishName());
        }
    }
}

// 餐厅点餐系统使用责任链模式
public class RestaurantOrderSystem {
    public static void main(String[] args) {
        Chef chineseChef = new ChineseChef();
        Chef westernChef = new WesternChef();
        Chef dessertChef = new DessertChef();

        // 构建责任链
        chineseChef.setNextChef(westernChef);
        westernChef.setNextChef(dessertChef);

        // 发起点餐请求
        Order order1 = new Order("Kung Pao Chicken", "Chinese");
        chineseChef.handleOrder(order1);

        Order order2 = new Order("Steak", "Western");
        chineseChef.handleOrder(order2);

        Order order3 = new Order("Tiramisu", "Dessert");
        chineseChef.handleOrder(order3);

        Order order4 = new Order("Sushi", "Japanese");
        chineseChef.handleOrder(order4);
    }
}

在这个示例中,不同类型的菜品(中餐、西餐、甜点等)由不同的厨师负责。点餐请求会从低级别处理器传递到更高级别处理器,直到找到能够处理该类型的厨师,或者请求到达责任链的末端。

2.4 简单的权限验证

让我们考虑一个简单的权限验证场景,使用责任链模式来处理不同级别的权限检查。不同级别的权限检查由不同的权限处理者来执行,如果某个处理者无法处理权限请求,则请求将被传递给下一个处理者。

以下是使用责任链模式模拟权限验证的示例:

java 复制代码
// 权限请求
class PermissionRequest {
    private String username;
    private int level;

    public PermissionRequest(String username, int level) {
        this.username = username;
        this.level = level;
    }

    public String getUsername() {
        return username;
    }

    public int getLevel() {
        return level;
    }
}

// 权限处理者接口
interface PermissionHandler {
    void setNextHandler(PermissionHandler nextHandler);
    void handleRequest(PermissionRequest request);
}

// 基础权限处理者
class BasicPermissionHandler implements PermissionHandler {
    private PermissionHandler nextHandler;

    @Override
    public void setNextHandler(PermissionHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(PermissionRequest request) {
        if (request.getLevel() <= 10) {
            System.out.println(request.getUsername() + " has basic permission level.");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 中级权限处理者
class IntermediatePermissionHandler implements PermissionHandler {
    private PermissionHandler nextHandler;

    @Override
    public void setNextHandler(PermissionHandler nextHandler) {
        this.nextHandler = nextHandler;
    }

    @Override
    public void handleRequest(PermissionRequest request) {
        if (request.getLevel() <= 50) {
            System.out.println(request.getUsername() + " has intermediate permission level.");
        } else if (nextHandler != null) {
            nextHandler.handleRequest(request);
        }
    }
}

// 高级权限处理者
class AdvancedPermissionHandler implements PermissionHandler {
    @Override
    public void setNextHandler(PermissionHandler nextHandler) {
        // AdvancedPermissionHandler is the final handler and does not require a next handler
    }

    @Override
    public void handleRequest(PermissionRequest request) {
        if (request.getLevel() > 50) {
            System.out.println(request.getUsername() + " has advanced permission level.");
        } else {
            System.out.println("No handler found for " + request.getUsername());
        }
    }
}

// 使用责任链模式进行权限验证
public class PermissionChainExample {
    public static void main(String[] args) {
        PermissionHandler basicHandler = new BasicPermissionHandler();
        PermissionHandler intermediateHandler = new IntermediatePermissionHandler();
        PermissionHandler advancedHandler = new AdvancedPermissionHandler();

        // 构建权限处理链
        basicHandler.setNextHandler(intermediateHandler);
        intermediateHandler.setNextHandler(advancedHandler);

        // 发起权限请求
        PermissionRequest request1 = new PermissionRequest("UserA", 5);
        basicHandler.handleRequest(request1);

        PermissionRequest request2 = new PermissionRequest("UserB", 30);
        basicHandler.handleRequest(request2);

        PermissionRequest request3 = new PermissionRequest("UserC", 60);
        basicHandler.handleRequest(request3);

        PermissionRequest request4 = new PermissionRequest("UserD", 100);
        basicHandler.handleRequest(request4);
    }
}

在此示例中,不同级别的权限请求由不同级别的处理者处理。请求会从低级别处理者传递到更高级别处理者,直到找到能够处理该权限请求的处理者,或者请求到达责任链的末端。

2.5 工程师

让我们想象一个问题解决系统,根据问题的复杂程度,系统中的不同专家级别的工程师会负责处理不同级别的问题。如果一个工程师无法解决问题,请求将被传递给下一个更高级别的工程师。

以下是使用责任链模式模拟问题解决系统的示例:

java 复制代码
// 问题请求
class Problem {
    private String description;
    private int complexity;

    public Problem(String description, int complexity) {
        this.description = description;
        this.complexity = complexity;
    }

    public String getDescription() {
        return description;
    }

    public int getComplexity() {
        return complexity;
    }
}

// 工程师接口
interface Engineer {
    void setNextEngineer(Engineer nextEngineer);
    void solveProblem(Problem problem);
}

// 初级工程师
class JuniorEngineer implements Engineer {
    private Engineer nextEngineer;

    @Override
    public void setNextEngineer(Engineer nextEngineer) {
        this.nextEngineer = nextEngineer;
    }

    @Override
    public void solveProblem(Problem problem) {
        if (problem.getComplexity() <= 5) {
            System.out.println("Junior Engineer solved problem: " + problem.getDescription());
        } else if (nextEngineer != null) {
            nextEngineer.solveProblem(problem);
        }
    }
}

// 中级工程师
class IntermediateEngineer implements Engineer {
    private Engineer nextEngineer;

    @Override
    public void setNextEngineer(Engineer nextEngineer) {
        this.nextEngineer = nextEngineer;
    }

    @Override
    public void solveProblem(Problem problem) {
        if (problem.getComplexity() <= 10) {
            System.out.println("Intermediate Engineer solved problem: " + problem.getDescription());
        } else if (nextEngineer != null) {
            nextEngineer.solveProblem(problem);
        }
    }
}

// 高级工程师
class SeniorEngineer implements Engineer {
    @Override
    public void setNextEngineer(Engineer nextEngineer) {
        // SeniorEngineer is the final engineer and does not require a next engineer
    }

    @Override
    public void solveProblem(Problem problem) {
        if (problem.getComplexity() > 10) {
            System.out.println("Senior Engineer solved problem: " + problem.getDescription());
        } else {
            System.out.println("No engineer found for problem: " + problem.getDescription());
        }
    }
}

// 使用责任链模式解决问题
public class ProblemSolvingSystem {
    public static void main(String[] args) {
        Engineer juniorEngineer = new JuniorEngineer();
        Engineer intermediateEngineer = new IntermediateEngineer();
        Engineer seniorEngineer = new SeniorEngineer();

        // 构建问题解决链
        juniorEngineer.setNextEngineer(intermediateEngineer);
        intermediateEngineer.setNextEngineer(seniorEngineer);

        // 发起问题解决请求
        Problem problem1 = new Problem("Bug fixing", 3);
        juniorEngineer.solveProblem(problem1);

        Problem problem2 = new Problem("Algorithm optimization", 8);
        juniorEngineer.solveProblem(problem2);

        Problem problem3 = new Problem("System architecture design", 15);
        juniorEngineer.solveProblem(problem3);

        Problem problem4 = new Problem("Network setup", 20);
        juniorEngineer.solveProblem(problem4);
    }
}

在此示例中,不同级别的工程师由不同级别的处理者处理。问题请求会从低级别处理者传递到更高级别处理者,直到找到能够解决该问题的工程师,或者请求到达责任链的末端。

相关推荐
越甲八千3 小时前
重温设计模式--代理、中介者、适配器模式的异同
设计模式·适配器模式
信徒_5 小时前
常用设计模式
java·单例模式·设计模式
爱码少年11 小时前
springboot中责任链模式之简单应用
spring boot·责任链模式
lxyzcm1 天前
深入理解C++23的Deducing this特性(上):基础概念与语法详解
开发语言·c++·spring boot·设计模式·c++23
越甲八千1 天前
重温设计模式--单例模式
单例模式·设计模式
Vincent(朱志强)1 天前
设计模式详解(十二):单例模式——Singleton
android·单例模式·设计模式
诸葛悠闲1 天前
设计模式——桥接模式
设计模式·桥接模式
捕鲸叉1 天前
C++软件设计模式之外观(Facade)模式
c++·设计模式·外观模式
小小小妮子~1 天前
框架专题:设计模式
设计模式·框架
先睡1 天前
MySQL的架构设计和设计模式
数据库·mysql·设计模式