策略模式是一種非常容易理解的設計模式,其最常見的應用場景是,利用它來避免冗長的 if-else 或 switch 分支判斷。 ...
簡介
策略設計模式(Strategy Design Pattern)實際上起到一個解耦的作用,解耦了策略的定義、創建、使用三部分。
其概念是,定義一系列演算法類,將每一個演算法封裝起來,並讓它們可以互相替換。
從代碼的層面上理解就是,將面向過程編程中的分支(如 if-else 或 switch 分支)代碼,轉換成面向對象的演算法類,通過構建這些類的關係以實現不同分支的選擇,實現運行時選擇策略。
具體實現
在這裡,使用一個加、減、乘的案例來展示策略模式的應用。
首先,對加、減、乘運算抽象出一個公共的方法,定義一個 Strategy
策略介面,其代碼示例如下:
public interface Strategy {
// 加、減、乘、除都是對兩個數進行處理
int doOperation(int num1, int num2);
}
對於加法,實現 Strategy
策略介面,定義一個 OperationAdd
策略類,其代碼示例如下:
public class OperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
對於減法,實現 Strategy
策略介面,定義一個 OperationSubtract
策略類,其代碼示例如下:
public class OperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
對於乘法,實現 Strategy
策略介面,定義一個 OperationMultiply
策略類,其代碼示例如下:
public class OperationMultiply implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
通常,會定義一個 Context
類用於彙總策略類,以方便客戶端使用,其代碼示例如下:
public class Context {
private final Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2) {
return strategy.doOperation(num1, num2);
}
}
對於客戶端而言,需要理解 Context
類如何使用,以及知道所有的策略類,通過註入不同的 Strategy
對象以達到選擇不同策略的效果。
如下是客戶端使用策略模式的代碼示例:
public class StrategyDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
// 10 + 5 = 15
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
// 10 - 5 = 5
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
// 10 * 5 = 50
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
總結
優點
策略模式的主要優點如下:
- 使用策略模式可以避免使用多重條件語句,如 if-else 或 switch 語句
- 策略模式提供了管理相關演算法族的辦法,如恰當地使用繼承把演算法族的公共代碼轉移到父類中
- 策略模式提供了相同行為的不同實現,客戶端可以根據不同的需求使用不同的策略
- 可以在不更改原代碼的模式下,靈活增加新的演算法,符合開閉原則
- 策略模式把演算法的使用放到環境類中,把實現放到具體策略類中,把定義放到客戶端中,實現了三者的解耦
缺點
策略模式的主要缺點如下:
- 客戶端必須知道所有的策略類,並自行決定使用哪一個策略類
- 策略模式造成很多策略類,增加了維護難度
適用場景
策略模式的適用場景如下:
- 一個系統需要動態地在幾種演算法中選擇一種時,可將每個演算法封裝到策略類中
- 對於多重條件語句,使用策略模式將這些行為轉移到相應的具體策略類中,以替代這些條件語句
- 系統要求使用演算法的客戶端不應該知道其操作的數據時,可以使用策略模式來封裝演算法及其數據結構
源碼
在 JDK 中,Comparator
介面就是一個策略模式的應用。
實際使用時,Comparator
就是策略介面,使用匿名內部類來實現具體策略類。如下是使用的示例代碼:
import java.util.Arrays;
import java.util.Comparator;
public class ComparatorDemo {
public static void main(String[] args) {
String[] names = {"張三", "李四", "小明"};
Comparator<String> comparator = new Comparator<>() {
@Override
public int compare(String o1, String o2) {
return o1.compareTo(o2);
}
};
Arrays.sort(names, comparator);
// [小明, 張三, 李四]
System.out.println(Arrays.toString(names));
}
}