深入理解Java設計模式之策略模式
一、什么是策略模式
策略模式定義了一系列算法,并將每個算法封裝起來,使他們可以相互替換,且算法的變化不會影響到使用算法的客戶。需要設計一個接口,為一系列實現(xiàn)類提供統(tǒng)一的方法,多個實現(xiàn)類實現(xiàn)該接口,設計一個抽象類(可有可無,屬于輔助類),提供輔助函數(shù)。
策略模式定義和封裝了一系列的算法,它們是可以相互替換的,也就是說它們具有共性,而它們的共性就體現(xiàn)在策略接口的行為上,另外為了達到最后一句話的目的,也就是說讓算法獨立于使用它的客戶而獨立變化,我們需要讓客戶端依賴于策略接口。
一種很簡單的解釋,在我們的開發(fā)過程中,經(jīng)常會遇到大量的if...else或者switch...case語句,當這些語句在開發(fā)中只是為了起到分流作用,這些分流和業(yè)務邏輯無關,那么這個時候就可以考慮用策略模式。
二、策略模式的結構

這個模式涉及到三個角色:
上下文環(huán)境(Context)角色:持有一個Strategy的引用。
抽象策略(Strategy)角色:這是一個抽象角色,通常由一個接口或抽象類實現(xiàn)。此角色給出所有的具體策略類所需的接口。
具體策略(ConcreteStrategy)角色:包裝了相關的算法或行為
三、策略模式的應用場景
舉一個例子,商場搞促銷--打8折,滿200送50,滿1000送禮物,這種促銷就是策略。
再舉一個例子,dota里面的戰(zhàn)術,玩命四保一,三偽核體系,推進體系,大招流體系等,這些戰(zhàn)術都是一種策略。
應用場景:
1、 多個類只區(qū)別在表現(xiàn)行為不同,可以使用Strategy模式,在運行時動態(tài)選擇具體要執(zhí)行的行為。
2、 需要在不同情況下使用不同的策略(算法),或者策略還可能在未來用其它方式來實現(xiàn)。
3、 對客戶隱藏具體策略(算法)的實現(xiàn)細節(jié),彼此完全獨立。
四、策略模式的優(yōu)缺點
優(yōu)點:
1、結構清晰,把策略分離成一個個單獨的類「替換了傳統(tǒng)的 if else」2、代碼耦合度降低,安全性提高「各個策略的細節(jié)被屏蔽」
缺點:
1、客戶端必須要知道所有的策略類,否則你不知道該使用那個策略,所以策略模式適用于提前知道所有策略的情況下2、策略類數(shù)量增多(每一個策略類復用性很小,如果需要增加算法,就只能新增類)五、策略模式和簡單工廠模式的異同
在上篇文章已經(jīng)提過了,傳送地址:深入理解設計模式(二):簡單工廠模式
六、策略模式的實現(xiàn)
Strategy類,定義所有支持的算法的公共接口
//Strategy類,定義所有支持的算法的公共接口
abstract class Strategy
{
//算法方法
public abstract void AlgorithmInterface();
}
oncreteStrategy,封裝了具體的算法或行為,繼承于Strategy
//算法A
class ConcreteStrategyA : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法A的實現(xiàn)");
}
}
//算法B
class ConcreteStrategyB : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法B的實現(xiàn)");
}
}
//算法C
class ConcreteStrategyC : Strategy
{
public override void AlgorithmInterface()
{
Console.WriteLine("算法C的實現(xiàn)");
}
}
Context,用一個ConcreteStrategy來配置,維護一個對Strategy對象的引用
//Context,用一個ConcreteStrategy來配置,維護一個對Strategy對象的引用
class Context
{
Strategy Strategy;
public Context(Strategy Strategy)
{
this.Strategy = Strategy;
}
//上下文接口
public void ContextInterface()
{
Strategy.AlgorithmInterface();
}
}
客戶端代碼
static void Main(string[] args)
{
Context Context;
Context = new Context(new ConcreteStrategyA());
Context.ContextInterface();
Context = new Context(new ConcreteStrategyB());
Context.ContextInterface();
Context = new Context(new ConcreteStrategyC());
Context.ContextInterface();
Console.Read();
}
七、策略模式和簡單工廠模式的結合
改造后的Context
class Context
{
Strategy Strategy=null;
public Context(string type)
{
switch (type)
{
case "A":
ConcreteStrategyA A = new ConcreteStrategyA();
Strategy = A;
break;
case "B":
ConcreteStrategyB B = new ConcreteStrategyB();
Strategy = B;
break;
case "C":
ConcreteStrategyC C = new ConcreteStrategyC();
Strategy = C;
break;
}
}
//上下文接口
public void ContextInterface()
{
Strategy.AlgorithmInterface();
}
}
改造后的客戶端代碼
static void Main(string[] args)
{
Context Context = new Context("這里是相應的算法類型字符串");
Context.ContextInterface();
Console.Read();
}
對比下改造前后的區(qū)別不難看出,改造前客戶端需要認識兩個類,Context和ConcreteStrategy。而策略模式和簡單工廠模式結合后,客戶端只需要認識一個類Context,降低了耦合性。
八、策略枚舉的實現(xiàn)
我們可以使用枚舉在一個類中實現(xiàn)以上所有的功能及三種不同的角色,下面看看怎么通過枚舉來實現(xiàn)策略模式
public enum Calculator
{ ADD("+") {
public int exec(int a, int b) {
return a+b;
}
},
SUB("-") {
public int exec(int a, int b) {
return a-b;
}
};
public abstract int exec(int a, int b);
//運算符
private String value = "";
private Calculator(String value)
{
this.value = value;
}
public String getValue()
{
return value;
}
}
在枚舉類中,定義的抽象方法就像當時之前的接口,每一個枚舉ADD SUB相當是一個具體的實現(xiàn)類(策略角色),而整個枚舉類就是策略的分裝角色。
這是從網(wǎng)上copy的代碼,本人不怎么喜歡這么寫,總感覺違背了代碼規(guī)范。
九、總結
策略模式,實質就是封裝了一些算法,讓算法可以互相替換,用戶可以自由選擇這些算法進行操作。策略模式本身理解起來沒什么難點,但是在實際應用中其本身主要結合工廠模式一起使用。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!
相關文章
Java 高并發(fā)九:鎖的優(yōu)化和注意事項詳解
本文主要介紹Java高并發(fā)鎖的優(yōu)化和注意事項,這里整理了詳細的資料,并講解了 1. 鎖優(yōu)化的思路和方法 2. 虛擬機內的鎖優(yōu)化 3. 一個錯誤使用鎖的案例 4. ThreadLocal及其源碼分析等知識,有需要的小伙伴可以參考下2016-09-09
淺談spring-boot的單元測試中,@Before不被執(zhí)行的原因
這篇文章主要介紹了淺談spring-boot的單元測試中,@Before不被執(zhí)行的原因,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-04-04

