天天看點

面試官:責任鍊和政策設計模式,你确定了解嗎,程式員之路真坎坷

作者:網際網路技術學堂

引言

責任鍊(Chain of Responsibility)和政策(Strategy)設計模式是兩種經典的行為型設計模式,在 Java 開發中被廣泛應用。本文将分析這兩種設計模式的使用場景、類圖結構、Spring AOP 架構中的應用、責任鍊設計模式在 Spring AOP 架構中的應用、優勢和劣勢,以及在 Spring 中展現的點。

大家好,這裡是網際網路技術學堂,留下你的點贊、關注、分享,您的支援是我創作的源泉,謝謝。

責任鍊設計模式

使用場景

責任鍊設計模式适用于一個任務需要多個處理者來處理,但是具體處理任務的處理者在任務送出前無法确定。比如日常生活中的請假流程,一個員工請假需要經過多個上司層級的審批,不同層級的上司有不同的審批權限和決策能力,當一個上司處理不了這個請求時,會将請求傳遞給下個上司。這個過程就是一個典型的責任鍊模式。

面試官:責任鍊和政策設計模式,你确定了解嗎,程式員之路真坎坷

類圖結構

責任鍊模式由三個部分組成:抽象處理者、具體處理者和用戶端。抽象處理者定義了處理請求的接口,并且維護了一個指向下一個處理者的引用;具體處理者實作了處理請求的具體邏輯,并且可以選擇将請求傳遞給下一個處理者;用戶端負責建立責任鍊,并将請求發送給責任鍊的首要處理者。

責任鍊設計模式類圖

面試官:責任鍊和政策設計模式,你确定了解嗎,程式員之路真坎坷

Spring AOP 架構中的應用

Spring AOP 架構中的切面(Aspect)就是一個責任鍊,每個切面都是一個處理者,可以選擇處理請求或将請求傳遞給下一個切面。Spring AOP 架構中的切面可以使用注解或 XML 配置的方式定義,具體實作方式類似于責任鍊模式中的具體處理者。Spring AOP 架構中的切點(Pointcut)定義了哪些方法需要被切入,可以使用注解或 XML 配置的方式定義,類似于責任鍊模式中的用戶端。

責任鍊設計模式在 Spring AOP 架構中的應用

Spring AOP 架構中的切面可以使用責任鍊模式來實作,每個切面都可以選擇處理請求或将請求傳遞給下一個切面。使用責任鍊模式可以讓切面的處理邏輯更加清晰、靈活和可擴充。

面試官:責任鍊和政策設計模式,你确定了解嗎,程式員之路真坎坷

優勢和劣勢

優勢

  • 責任鍊模式可以将一個任務拆分成多個子任務,每個子任務由一個具體處理者來處理,實作了解耦。
  • 責任鍊模式可以動态地調整責任鍊中的處理者。
  • 責任鍊模式可以避免在用戶端中使用大量的 if-else 語句,使代碼更加簡潔、可維護和可擴充。
  • 責任鍊模式可以在運作時動态地添加、删除或修改處理者,實作了動态性。

劣勢

  • 責任鍊模式可能存在處理請求的處理者鍊過長的問題,影響處理性能。
  • 責任鍊模式可能存在某個處理者無法處理請求的問題,需要謹慎設計處理者鍊。

在 Spring 中展現的點

在 Spring 中,責任鍊模式可以通過 AOP 和 Bean Post Processor 來展現。

在 AOP 中,切面就是一個責任鍊,每個切面都是一個具體處理者,可以選擇處理請求或将請求傳遞給下一個切面。

在 Bean Post Processor 中,可以通過繼承 AbstractBeanFactoryPostProcessor 類來實作一個 Bean 處理器的責任鍊。每個 Bean 處理器都是一個具體處理者,可以選擇處理 Bean 或将 Bean 傳遞給下一個處理器。

Spring AOP 中使用責任鍊模式的示例代碼

@Aspect
public class MyAspect {
@Around("execution(* com.example.service.*.*(..))")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
// 執行前置處理
// ...
Object result = pjp.proceed();
// 執行後置處理
// ...
return result;
}
}           

政策設計模式

使用場景

政策設計模式适用于一個任務有多個不同的實作方式,且需要在運作時動态地選擇其中一種實作方式。比如日常生活中的出行方式,可以選擇騎自行車、坐公共汽車、打車或開私家車等不同的實作方式,具體選擇哪種方式取決于具體情況,如時間、距離、費用等。

面試官:責任鍊和政策設計模式,你确定了解嗎,程式員之路真坎坷

類圖結構

政策模式由三個部分組成:政策接口、具體政策和用戶端。政策接口定義了所有政策的公共接口,具體政策實作了政策接口中的方法,用戶端負責建立政策對象,并在運作時選擇具體的政策對象。

政策設計模式類圖

面試官:責任鍊和政策設計模式,你确定了解嗎,程式員之路真坎坷

責任鍊模式示例代碼

// 定義抽象處理者
public abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(Request request);
}
// 具體處理者1
public class ConcreteHandler1 extends Handler {
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE1) {
// 處理請求
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
// 具體處理者2
public class ConcreteHandler2 extends Handler {
public void handleRequest(Request request) {
if (request.getType() == RequestType.TYPE2) {
// 處理請求
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
// 用戶端代碼
public class Client {
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
handler1.setSuccessor(handler2);
handler1.handleRequest(new Request(RequestType.TYPE2));
}
}
// 請求類
public class Request {
private RequestType type;
public Request(RequestType type) {
this.type = type;
}
public RequestType getType() {
return type;
}
}
// 請求類型枚舉
public enum RequestType {
TYPE1, TYPE2
}           

在上面的代碼中,抽象處理者類 Handler 定義了處理請求的抽象方法 handleRequest() 和一個後繼處理者 successor,具體處理者類 ConcreteHandler1 和 ConcreteHandler2 繼承了抽象處理者類并實作了具體的請求處理方法。用戶端代碼通過将具體處理者類連結起來并傳入一個請求對象來啟動整個責任鍊。

Spring AOP 架構中的應用

在 Spring AOP 架構中,政策模式可以通過使用注解或 XML 配置的方式來實作。使用注解可以通過 @Qualifier 注解來指定具體的政策對象,使用 XML 配置可以通過 <property> 元素來指定具體的政策對象。

面試官:責任鍊和政策設計模式,你确定了解嗎,程式員之路真坎坷

政策設計模式示例代碼

// 抽象政策接口
public interface Strategy {
void execute();
}
// 具體政策類1
public class ConcreteStrategy1 implements Strategy {
public void execute() {
// 具體實作
}
}
// 具體政策類2
public class ConcreteStrategy2 implements Strategy {
public void execute() {
// 具體實作
}
}
// 上下文類
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void executeStrategy() {
strategy.execute();
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}
// 用戶端代碼
public class Client {
public static void main(String[] args) {
Context context = new Context(new ConcreteStrategy1());
context.executeStrategy();
context.setStrategy(new ConcreteStrategy2());
context.executeStrategy();
}
}           

在上面的代碼中,抽象政策接口 Strategy 定義了政策方法 execute(),具體政策類 ConcreteStrategy1 和 ConcreteStrategy2 實作了政策方法。上下文類 Context持有一個政策對象,并在用戶端代碼中設定具體的政策對象來執行不同的政策。

優勢和劣勢

優勢

政策模式可以在運作時動态地選擇具體的實作方式,實作了可擴充性。

政策模式可以避免使用大量的 if-else 語句,使代碼更加簡潔、可維護和可擴充。

劣勢

  • 政策模式需要在用戶端顯式地建立和選擇具體的政策對象,對用戶端編碼要求較高。
  • 政策模式可能存在多個政策之間重複代碼的問題,需要謹慎設計。

在 Spring 中展現的點

在 Spring 中,政策模式可以通過依賴注入和條件注解來展現。

依賴注入可以通過将具體的政策對象注入到用戶端中來實作,進而避免用戶端顯式地建立和選擇具體的政策對象。

條件注解可以通過 @Conditional 注解來根據條件選擇具體的政策對象。條件注解可以根據環境、配置或其他條件來選擇具體的政策對象,實作了更加靈活的政策選擇。

Spring AOP 中的政策設計模式應用

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Strategy {
String value();
}
@Service
@Strategy("A")
public class StrategyA implements MyStrategy {
public void execute() {
// 具體實作
}
}
@Service
@Strategy("B")
public class StrategyB implements MyStrategy {
public void execute() {
// 具體實作
}
}
@Component
public class StrategyExecutor {
@Autowired
private List<MyStrategy> strategies;
public void execute(String strategyType) {
for (MyStrategy strategy : strategies) {
if (strategy.getClass().isAnnotationPresent(Strategy.class)
&& strategy.getClass().getAnnotation(Strategy.class).value().equals(strategyType)) {
strategy.execute();
}
}
}
}
public interface MyStrategy {
void execute();
}
public class Client {
public static void main(String[] args) {
StrategyExecutor executor = new StrategyExecutor();
executor.execute("A");
}
}           

在上面的代碼中,@Strategy 注解用于标注具體的政策類,StrategyExecutor 類持有一個政策清單,并通過 execute() 方法來執行指定的政策。在用戶端代碼中,可以通過傳入不同的參數來執行不同的政策。

總結

責任鍊模式和政策設計模式都是常用的設計模式,它們可以提高代碼的可維護性和可擴充性。在 Spring 中,這兩種設計模式可以通過 AOP、Bean Post Processor、依賴注入和條件注解等方式來展現。當需要實作多個處理者的請求處理或多種實作方式的選擇時,可以考慮使用責任鍊模式和政策設計模式。

繼續閱讀