策略設計模式(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));
}
}
策略模式的主要優點如下:
策略模式的主要缺點如下:
策略模式的適用場景如下:
在 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));
}
}