設(shè)計模式之策略模式
策略模式
在策略模式(Strategy Pattern)中囱持,一個類的行為或其算法可以在運行時更改。
這種類型的設(shè)計模式屬于行為型模式。
在策略模式中,我們創(chuàng)建表示各種策略的對象和一個行為隨著策略對象改變而改變的 context 對象膘掰。
策略對象改變 context 對象的執(zhí)行算法。策略模式是指有一定行動內(nèi)容的相對穩(wěn)定的策略名稱佳遣。策略模式在古代中又稱“計策”识埋,簡稱“計”,
如《漢書·高帝紀上》:“漢王從其計”零渐。這里的“計”指的就是計謀窒舟、策略。策略模式具有相對穩(wěn)定的形式诵盼,
如“避實就虛”惠豺、“出奇制勝”等银还。一定的策略模式,既可應(yīng)用于戰(zhàn)略決策洁墙,也可應(yīng)用于戰(zhàn)術(shù)決策蛹疯;
既可實施于大系統(tǒng)的全局性行動,也可實施于大系統(tǒng)的局部性行動热监。
先直接貼栗子吧捺弦,概念在文章最后會介紹,也可以自行百度
我們有一個系統(tǒng)對接了各大主流的新聞網(wǎng)站孝扛,在我們的系統(tǒng)在中錄入新聞可以實現(xiàn)一鍵發(fā)布到指定的網(wǎng)站中羹呵,
現(xiàn)在需要實現(xiàn)這個功能。主要需求:
- 各個網(wǎng)站的對接邏輯不同疗琉,需要解耦冈欢。
- 對于客戶端的使用習慣不能有影響。
考慮再三決定使用策略模式來解決
步驟一:創(chuàng)建一個上傳接口
/**
* 上傳接口
*
* @author shenjg
* @date 2019/07/23
**/
public interface UploadService {
/**
* 上傳數(shù)據(jù)到網(wǎng)站
*
* @param object
*/
void uploadToWeb(Object object);
}
步驟二:針對不同網(wǎng)站實現(xiàn)接口
/**
* 上傳數(shù)據(jù)到百度
*
* @author shenjg
* @date 2019/07/23
**/
public class BaiduUploadService implements UploadService {
@Override
public void uploadToWeb(Object object) {
// do something
System.out.println("執(zhí)行上傳到百度所需要的邏輯" + object);
}
}
/**
* 上傳數(shù)據(jù)到新浪
*
* @author shenjg
* @date 2019/07/23
**/
public class SinaUploadService implements UploadService {
@Override
public void uploadToWeb(Object object) {
// do something
System.out.println("執(zhí)行上傳到新浪所需要的邏輯" + object);
}
}
/**
* 上傳數(shù)據(jù)到騰訊
*
* @author shenjg
* @date 2019/07/23
**/
public class TencentUploadService implements UploadService {
@Override
public void uploadToWeb(Object object) {
// do something
System.out.println("執(zhí)行上傳到騰訊所需要的邏輯" + object);
}
}
步驟三:創(chuàng)建context
/**
* @author shenjg
* @date 2019/07/23
**/
public class UploadContext {
private UploadService uploadService;
public UploadContext(UploadService uploadService) {
this.uploadService = uploadService;
}
public void uploadToWeb(Object object) {
uploadService.uploadToWeb(object);
}
}
步驟四:測試
/**
* 策略模式測試類
*
* @author shenjg
* @date 2019/07/23
**/
public class StrategyTest {
public static void main(String[] args) {
Object object = new Object();
// 上傳object到百度
UploadContext baiduUpload = new UploadContext(new BaiduUploadService());
baiduUpload.uploadToWeb(object);
// 上傳object到騰訊
UploadContext tencentUpload = new UploadContext(new TencentUploadService());
tencentUpload.uploadToWeb(object);
// 上傳object到新浪
UploadContext sinaUpload = new UploadContext(new SinaUploadService());
sinaUpload.uploadToWeb(object);
}
}
輸出打印
執(zhí)行上傳到百度所需要的邏輯java.lang.Object@610455d6
執(zhí)行上傳到騰訊所需要的邏輯java.lang.Object@610455d6
執(zhí)行上傳到新浪所需要的邏輯java.lang.Object@610455d6
點擊查看完整代碼github
介紹
策略模式作為一種軟件設(shè)計模式盈简,指對象有某個行為凑耻,但是在不同的場景中,該行為有不同的實現(xiàn)算法柠贤。例如:
我們需要上傳同一篇文章到新浪香浩、騰訊、百度三大網(wǎng)站中臼勉,此時系統(tǒng)針對不同網(wǎng)站就需要不同的對接邏輯邻吭。
策略模式:
- 定義了一組算法(業(yè)務(wù)規(guī)則);
- 封裝了每個算法宴霸;
- 這族的算法可互換代替(interchangeable)
組成
- 抽象策略角色: 策略類囱晴,通常由一個接口或者抽象類實現(xiàn)。
- 具體策略角色:包裝了相關(guān)的算法和行為瓢谢。
- 環(huán)境角色:持有一個策略類的引用畸写,最終給客戶端調(diào)用。
策略模式UML圖
應(yīng)用場景:
- 多個類只區(qū)別在表現(xiàn)行為不同氓扛,可以使用Strategy模式枯芬,在運行時動態(tài)選擇具體要執(zhí)行的行為。
- 需要在不同情況下使用不同的策略(算法)采郎,或者策略還可能在未來用其它方式來實現(xiàn)千所。
- 對客戶隱藏具體策略(算法)的實現(xiàn)細節(jié),彼此完全獨立蒜埋。
優(yōu)缺點
優(yōu)點
- 策略模式提供了管理相關(guān)的算法族的辦法淫痰。策略類的等級結(jié)構(gòu)定義了一個算法或行為族。恰當使用繼承可以把公共的代碼轉(zhuǎn)移到父類里面理茎,從而避免重復(fù)的代碼黑界。
- 策略模式提供了可以替換繼承關(guān)系的辦法管嬉。繼承可以處理多種算法或行為。如果不是用策略模式朗鸠,那么使用算法或行為的環(huán)境類就可能會有一些子類蚯撩,每一個子類提供一個不同的算法或行為。但是烛占,這樣一來算法或行為的使用者就和算法或行為本身混在一起胎挎。決定使用哪一種算法或采取哪一種行為的邏輯就和算法或行為的邏輯混合在一起,從而不可能再獨立演化忆家。繼承使得動態(tài)改變算法或行為變得不可能犹菇。
- 使用策略模式可以避免使用多重條件轉(zhuǎn)移語句。多重轉(zhuǎn)移語句不易維護芽卿,它把采取哪一種算法或采取哪一種行為的邏輯與算法或行為的邏輯混合在一起揭芍,統(tǒng)統(tǒng)列在一個多重轉(zhuǎn)移語句里面,比使用繼承的辦法還要原始和落后卸例。
缺點
- 客戶端必須知道所有的策略類称杨,并自行決定使用哪一個策略類。這就意味著客戶端必須理解這些算法的區(qū)別筷转,以便適時選擇恰當?shù)乃惴惞迷Q言之,策略模式只適用于客戶端知道所有的算法或行為的情況呜舒。
- 策略模式造成很多的策略類锭汛,每個具體策略類都會產(chǎn)生一個新類。有時候可以通過把依賴于環(huán)境的狀態(tài)保存到客戶端里面袭蝗,而將策略類設(shè)計成可共享的唤殴,這樣策略類實例可以被不同客戶端使用。換言之呻袭,可以使用享元模式來減少對象的數(shù)量眨八。