1. 概念
責(zé)任鏈設(shè)計模式是一種行為設(shè)計模式,它允許你創(chuàng)建一個對象鏈。請求從鏈的一端進(jìn)入,并沿著鏈的路徑依次經(jīng)過各個對象,直至找到合適的處理者。每個對象都決定是否要處理該請求或?qū)⑵鋫鬟f給鏈中的下一個對象。
1.1 核心概念
-
Handler(處理者):每個處理者對象包含了處理請求的代碼。處理者通常定義一個處理方法來執(zhí)行請求處理,并決定是否將請求傳遞給下一個處理者。
-
鏈(Chain):處理者按照某種方式連接在一起,構(gòu)成一個處理鏈。請求進(jìn)入鏈的一端,并沿著鏈傳遞直至有一個處理者處理請求或者請求到達(dá)鏈的末端。
-
Request(請求):請求是要被處理的對象。每個處理者檢查請求并進(jìn)行處理,或?qū)⑵鋫鬟f給下一個處理者。
1.2 工作原理
- 當(dāng)一個請求進(jìn)入責(zé)任鏈時,它被傳遞給第一個處理者。
- 處理者決定是否處理請求,如果能處理則執(zhí)行相應(yīng)操作,如果不能處理則將請求傳遞給鏈中的下一個處理者。
- 這個過程會持續(xù)直到有一個處理者能夠處理請求或者請求到達(dá)鏈的末端。
1.3 優(yōu)勢
- 松散耦合:責(zé)任鏈模式允許你添加或修改處理者而無需修改現(xiàn)有代碼。
- 動態(tài)設(shè)置鏈:你可以動態(tài)設(shè)置處理鏈,在運(yùn)行時指定處理者的順序或者數(shù)量。
1.4 示例
舉個例子,假設(shè)有一個報銷審批系統(tǒng)。不同級別的員工有不同的報銷限額。責(zé)任鏈模式可以用來構(gòu)建審批流程,每個處理者代表一個管理層級,根據(jù)報銷金額來決定是否批準(zhǔn)請求。如果一個處理者無法批準(zhǔn)請求,則將請求傳遞給下一個處理者,直到得到最終的審批結(jié)果。
責(zé)任鏈模式在很多場景下都有應(yīng)用,特別是處理流程連續(xù)、需要靈活調(diào)整處理順序的場景。
2. 舉例
2.1 簡單的購買審批場景
當(dāng)使用責(zé)任鏈模式時,我們可以考慮一個簡單的購買審批場景。不同級別的員工有不同的審批權(quán)限,低級別員工的審批額度小,而高級別員工有更高的審批額度。如果一個員工無法批準(zhǔn)請求,請求將被傳遞給下一個更高級別的員工。
以下是一個使用Java實(shí)現(xiàn)責(zé)任鏈模式的示例:
// 定義請求類
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);
}
// 具體處理者實(shí)現(xiàn)
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.");
}
}
}
// 使用責(zé)任鏈模式
public class ChainOfResponsibilityExample {
public static void main(String[] args) {
Approver manager = new Manager();
Approver director = new Director();
Approver president = new President();
// 構(gòu)建責(zé)任鏈
manager.setNext(director);
director.setNext(president);
// 發(fā)起請求
PurchaseRequest request1 = new PurchaseRequest(500);
manager.processRequest(request1);
PurchaseRequest request2 = new PurchaseRequest(2500);
manager.processRequest(request2);
PurchaseRequest request3 = new PurchaseRequest(15000);
manager.processRequest(request3);
}
}
這個例子中,我們創(chuàng)建了不同級別的處理者(Manager、Director、President),并設(shè)置了它們的審批額度。然后我們建立了一個責(zé)任鏈,通過調(diào)用 processRequest 方法來處理不同額度的購買請求。請求會從低級別的員工一直傳遞到更高級別的員工,直到找到能夠批準(zhǔn)請求的員工。
2.2 在線文件處理系統(tǒng)
我們可以想象一個在線文件處理系統(tǒng)。不同類型的文件需要經(jīng)過不同的處理器進(jìn)行處理,如圖片文件、文本文件、視頻文件等。每個處理器能夠處理特定類型的文件,如果一個處理器無法處理該類型文件,請求將被傳遞給下一個處理器。
下面是一個使用責(zé)任鏈模式處理文件的簡單示例:
// 文件處理請求
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());
}
}
}
// 使用責(zé)任鏈模式處理文件
public class FileHandlerExample {
public static void main(String[] args) {
FileHandler imageHandler = new ImageHandler();
FileHandler textHandler = new TextHandler();
FileHandler videoHandler = new VideoHandler();
// 構(gòu)建處理鏈
imageHandler.setNext(textHandler);
textHandler.setNext(videoHandler);
// 發(fā)起文件處理請求
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);
}
}
在這個示例中,不同類型的文件經(jīng)過責(zé)任鏈,每個處理器(ImageHandler、TextHandler、VideoHandler)能夠處理特定類型的文件。文件請求會從低級別處理器傳遞到更高級別處理器,直到找到能夠處理該類型文件的處理器,或者請求到達(dá)責(zé)任鏈的末端。
2.3 簡單的餐廳點(diǎn)餐系統(tǒng)
讓我們考慮一個簡單的餐廳點(diǎn)餐系統(tǒng)的場景。假設(shè)不同類型的菜品由不同的廚師來負(fù)責(zé)制作,而服務(wù)員負(fù)責(zé)接收顧客的點(diǎn)餐請求并將其傳遞給合適的廚師。
下面是使用責(zé)任鏈模式模擬餐廳點(diǎn)餐系統(tǒng)的示例:
// 餐品訂單
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);
}
}
}
// 甜點(diǎn)廚師
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());
}
}
}
// 餐廳點(diǎn)餐系統(tǒng)使用責(zé)任鏈模式
public class RestaurantOrderSystem {
public static void main(String[] args) {
Chef chineseChef = new ChineseChef();
Chef westernChef = new WesternChef();
Chef dessertChef = new DessertChef();
// 構(gòu)建責(zé)任鏈
chineseChef.setNextChef(westernChef);
westernChef.setNextChef(dessertChef);
// 發(fā)起點(diǎn)餐請求
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);
}
}
在這個示例中,不同類型的菜品(中餐、西餐、甜點(diǎn)等)由不同的廚師負(fù)責(zé)。點(diǎn)餐請求會從低級別處理器傳遞到更高級別處理器,直到找到能夠處理該類型的廚師,或者請求到達(dá)責(zé)任鏈的末端。
2.4 簡單的權(quán)限驗(yàn)證
讓我們考慮一個簡單的權(quán)限驗(yàn)證場景,使用責(zé)任鏈模式來處理不同級別的權(quán)限檢查。不同級別的權(quán)限檢查由不同的權(quán)限處理者來執(zhí)行,如果某個處理者無法處理權(quán)限請求,則請求將被傳遞給下一個處理者。
以下是使用責(zé)任鏈模式模擬權(quán)限驗(yàn)證的示例:
// 權(quán)限請求
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;
}
}
// 權(quán)限處理者接口
interface PermissionHandler {
void setNextHandler(PermissionHandler nextHandler);
void handleRequest(PermissionRequest request);
}
// 基礎(chǔ)權(quán)限處理者
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);
}
}
}
// 中級權(quán)限處理者
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);
}
}
}
// 高級權(quán)限處理者
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());
}
}
}
// 使用責(zé)任鏈模式進(jìn)行權(quán)限驗(yàn)證
public class PermissionChainExample {
public static void main(String[] args) {
PermissionHandler basicHandler = new BasicPermissionHandler();
PermissionHandler intermediateHandler = new IntermediatePermissionHandler();
PermissionHandler advancedHandler = new AdvancedPermissionHandler();
// 構(gòu)建權(quán)限處理鏈
basicHandler.setNextHandler(intermediateHandler);
intermediateHandler.setNextHandler(advancedHandler);
// 發(fā)起權(quán)限請求
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);
}
}
在此示例中,不同級別的權(quán)限請求由不同級別的處理者處理。請求會從低級別處理者傳遞到更高級別處理者,直到找到能夠處理該權(quán)限請求的處理者,或者請求到達(dá)責(zé)任鏈的末端。
2.5 工程師
讓我們想象一個問題解決系統(tǒng),根據(jù)問題的復(fù)雜程度,系統(tǒng)中的不同專家級別的工程師會負(fù)責(zé)處理不同級別的問題。如果一個工程師無法解決問題,請求將被傳遞給下一個更高級別的工程師。
以下是使用責(zé)任鏈模式模擬問題解決系統(tǒng)的示例:文章來源:http://www.zghlxwxcb.cn/news/detail-743012.html
// 問題請求
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());
}
}
}
// 使用責(zé)任鏈模式解決問題
public class ProblemSolvingSystem {
public static void main(String[] args) {
Engineer juniorEngineer = new JuniorEngineer();
Engineer intermediateEngineer = new IntermediateEngineer();
Engineer seniorEngineer = new SeniorEngineer();
// 構(gòu)建問題解決鏈
juniorEngineer.setNextEngineer(intermediateEngineer);
intermediateEngineer.setNextEngineer(seniorEngineer);
// 發(fā)起問題解決請求
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);
}
}
在此示例中,不同級別的工程師由不同級別的處理者處理。問題請求會從低級別處理者傳遞到更高級別處理者,直到找到能夠解決該問題的工程師,或者請求到達(dá)責(zé)任鏈的末端。文章來源地址http://www.zghlxwxcb.cn/news/detail-743012.html
到了這里,關(guān)于設(shè)計模式之責(zé)任鏈模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!