Java-策略-設計模式(十二)
說明
策略模式是一種行為型設計模式,可以根據不同的策略來進行不同的操作,我們常用的switch case和if else其實都可以認為是策略的體現,但缺點是想擴充套件新策略,就要去修改原來的業務程式碼,違背了面向物件的思想和原則,而策略模式可以很好的解決這個問題。
策略模式的組成:
抽象策略角色: 策略類,通常由一個介面或者抽象類實現。
具體策略角色:包裝了相關的演算法和行為。
環境角色:持有一個策略類的引用,最終給客戶端呼叫。
程式碼
以一個簡單的計數器為例,加減乘除是不同的四種策略,輸入相同的數字,根據不同的策略可以獲取不同的結果。程式碼如下。
抽象策略角色,計算策略的介面
/**
* @author ctl
* @date 2021/1/23
*/
public interface Counter {
int getResult(int[] nums);
}
具體策略角色,加法策略
/**
* @author ctl
* @date 2021/1/23
* 加法
*/
public class Addition implements Counter {
@Override
public int getResult(int[] nums) {
int r = 0;
for (int num : nums) {
r += num;
}
return r;
}
}
具體策略角色,減法策略
/**
* @author ctl
* @date 2021/1/23
* 減法
*/
public class Subtraction implements Counter {
@Override
public int getResult(int[] nums) {
int r = 0;
for (int i = 0; i < nums.length - 1; i++) {
r = nums[i] - nums[i + 1];
}
return r;
}
}
具體策略角色,乘法策略
/**
* @author ctl
* @date 2021/1/23
* 乘法
*/
public class Multiplication implements Counter {
@Override
public int getResult(int[] nums) {
int r = 0;
for (int i = 0; i < nums.length - 1; i++) {
r = nums[i] * nums[i + 1];
}
return r;
}
}
具體策略角色,除法策略
/**
* @author ctl
* @date 2021/1/23
* 除法
*/
public class Division implements Counter {
@Override
public int getResult(int[] nums) {
int r = 0;
for (int i = 0; i < nums.length - 1; i++) {
r = nums[i] / nums[i + 1];
}
return r;
}
}
環境角色,持有策略物件
/**
* @author ctl
* @date 2021/1/23
*/
public class CountHelper {
private Counter counter;
public void setCounter(Counter counter) {
this.counter = counter;
}
public int calculate(int[] nums) {
return counter.getResult(nums);
}
}
測試類
/**
* @author ctl
* @date 2021/1/23
*/
public class StrategyMain {
public static void main(String[] args) {
int calculate;
CountHelper countHelper = new CountHelper();
int[] nums = {8, 2};
System.out.println("開始計算" + Arrays.toString(nums));
// 加法
countHelper.setCounter(new Addition());
calculate = countHelper.calculate(nums);
System.out.println("加法:" + calculate);
// 減法
countHelper.setCounter(new Subtraction());
calculate = countHelper.calculate(nums);
System.out.println("減法:" + calculate);
// 乘法
countHelper.setCounter(new Multiplication());
calculate = countHelper.calculate(nums);
System.out.println("乘法:" + calculate);
// 除法
countHelper.setCounter(new Division());
calculate = countHelper.calculate(nums);
System.out.println("除法:" + calculate);
}
}
結果
可以看到分別計算出了8,2對應加減乘除的結果。
總結
應用場景:
1、 多個類只區別在表現行為不同,可以使用策略模式,在執行時動態選擇具體要執行的行為。
2、 需要在不同情況下使用不同的策略(演算法),或者策略還可能在未來用其它方式來實現。
3、 對客戶隱藏具體策略(演算法)的實現細節,彼此完全獨立。
注意:
本例中的實現方式跟我之前寫橋接模式中舉例的實現方式有些類似,但千萬不要搞混。
策略模式是一種行為型設計模式,是要根據不同的行為來採用不同的策略。
橋接模式是一種結構型設計模式,是為了達到抽象與實現解耦的目的,減少繼承關係。
二者的本質和出發點及解決的問題是完全不同的,所以不要因為程式碼上有類似的地方而混淆了概念。
其實想寫出優雅的程式碼,並不是心裡想著要用哪種設計模式就行了,設計模式是為了讓我們更好的去理解面向物件的思想,但千萬不能墨守成規,為了設計而設計。
寫程式碼是一個不斷優化和重構的過程,在這個過程中,我們只要遵循了面向物件的編碼規範,回過頭來再看這些程式碼就會發現其實已經不自覺的用到了一些設計模式。
我認為真正的編碼大神不是使用設計模式來寫程式碼,而是他寫的程式碼,成為了設計模式。