摘要:策略模式使得算法可以在不影響到客戶端的情況下發生變化。下面就以一個示意性的實現講解策略模式實例的結構。抽象策略角色這是一個抽象角色,通常由一個接口或抽象類實現。優點策略模式提供了管理相關的算法族的辦法。
策略模式(Strategy Pattern)屬于對象行為型模式的一種,其用意是針對一組算法,將每一個算法封裝到具有共同接口的獨立的類中,從而使得它們可以相互替換。策略模式使得算法可以在不影響到客戶端的情況下發生變化。概述
策略模式: 是對算法的包裝,是把使用算法的責任和算法本身分割開來,委派給不同的對象管理。策略模式通常把一個系列的算法包裝到一系列的策略類里面,作為一個抽象策略類的子類。用一句話來說,就是:“準備一組算法,并將每一個算法封裝起來,使得它們可以互換”。下面就以一個示意性的實現講解策略模式實例的結構。
UML結構圖
模式結構
環境(Context)角色: 持有一個Strategy的引用。
抽象策略(Strategy)角色: 這是一個抽象角色,通常由一個接口或抽象類實現。此角色給出所有的具體策略類所需的接口。
具體策略(ConcreteStrategy)角色: 包裝了相關的算法或行為。
案例采用上文的UML圖以及分析出的模式結構,寫一個簡單的購物折扣功能
假設現在要上線一個販賣各類書籍的電子商務網站的折扣功能。一個最簡單的情況就是把所有貨品的單價乘上數量,但是實際情況肯定比這要復雜。比如,本網站可能對所有的高級會員提供每本20%的促銷折扣;對中級會員提供每本10%的促銷折扣;對初級會員沒有折扣。
根據描述,折扣是根據以下的幾個算法中的一個進行的:
算法一:對初級會員沒有折扣。
算法二:對中級會員提供10%的促銷折扣。
算法三:對高級會員提供20%的促銷折扣。
結構圖如下:
1.定義抽象折扣類
/** * 會員優惠策略 */ interface MemberStrategy { /** * 計算圖書的價格 * * @param booksPrice 圖書的原價 * @return 計算出打折后的價格 */ double calcPrice(double booksPrice); }
2.創建三個 具體策略類 ,代表三種不同計算規則
class PrimaryMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("對于初級會員的沒有折扣"); return booksPrice; } } class IntermediateMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("對于中級會員的折扣為10%"); return booksPrice * 0.9; } } class AdvancedMemberStrategy implements MemberStrategy { @Override public double calcPrice(double booksPrice) { System.out.println("對于高級會員的折扣為20%"); return booksPrice * 0.8; } }
3.創建 環境(Context)角色 價格類,持有抽象決策的引用
class Price { /** * 持有一個具體的策略對象 */ private MemberStrategy strategy; /** * 構造函數,傳入一個具體的策略對象 * * @param strategy 具體的策略對象 */ public Price(MemberStrategy strategy) { this.strategy = strategy; } /** * 計算圖書的價格 * * @param booksPrice 圖書的原價 * @return 計算出打折后的價格 */ public double quote(double booksPrice) { return this.strategy.calcPrice(booksPrice); } }
4.創建客戶端,用于測試
public class Client { public static void main(String[] args) { Price price; //創建環境 price = new Price(new PrimaryMemberStrategy()); //計算價格 System.out.println("圖書的最終價格為:" + price.quote(300)); //創建環境 price = new Price(new AdvancedMemberStrategy()); //計算價格 System.out.println("圖書的最終價格為:" + price.quote(300)); } }
6.運行結果
對于初級會員的沒有折扣 圖書的最終價格為:300.0 對于高級會員的折扣為20% 圖書的最終價格為:240.0
從上面的示例可以看出,策略模式僅僅封裝算法,提供新的算法插入到已有系統中,以及老算法從系統中“退休”的方法,策略模式并不決定在何時使用何種算法。在什么情況下使用什么算法是由客戶端決定的。
總結重心
策略模式的重心不是如何實現算法,而是如何組織、調用這些算法,從而讓程序結構更靈活,具有更好的維護性和擴展性。
算法平等性
策略模式一個很大的特點就是各個策略算法的平等性。對于一系列具體的策略算法,大家的地位是完全一樣的,正因為這個平等性,才能實現算法之間可以相互替換。所有的策略算法在實現上也是相互獨立的,相互之間是沒有依賴的。
所以可以這樣描述這一系列策略算法:策略算法是相同行為的不同實現。
策略的唯一性
運行期間,策略模式在每一個時刻只能使用一個具體的策略實現對象,雖然可以動態地在不同的策略實現中切換,但是同時只能使用一個。
公有的行為
經常見到的是,所有的具體策略類都有一些公有的行為。這時候,就應當把這些公有的行為放到共同的抽象策略角色Strategy類里面。當然這時候抽象策略角色必須要用Java抽象類實現,而不能使用接口。
這其實也是典型的將代碼向繼承等級結構的上方集中的標準做法。
優點
策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行為族。恰當使用繼承可以把公共的代碼移到父類里面,從而避免代碼重復。
使用策略模式可以避免使用多重條件(if-else)語句。多重條件語句不易維護,它把采取哪一種算法或采取哪一種行為的邏輯與算法或行為的邏輯混合在一起,統統列在一個多重條件語句里面,比使用繼承的辦法還要原始和落后。
缺點
客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。這就意味著客戶端必須理解這些算法的區別,以便適時選擇恰當的算法類。換言之,策略模式只適用于客戶端知道算法或行為的情況。
由于策略模式把每個具體的策略實現都多帶帶封裝成為類,如果備選的策略很多的話,那么對象的數目就會很可觀。
說點什么參考文獻:http://www.cnblogs.com/java-my-life/archive/2012/05/10/2491891.html
全文代碼:https://gitee.com/battcn/design-pattern/tree/master/Chapter18/battcn-strategy
個人QQ:1837307557
battcn開源群(適合新手):391619659
微信公眾號:battcn(歡迎調戲)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70802.html
摘要:設計模式的分類經典應用框架中常見的設計模式分為三類創建型模式對類的實例化過程的抽象。對象的結構模式是動態的。對象的行為模式則使用對象的聚合來分配行為。設計模式是個好東西,以后肯定還要進一步的學習,并且在項目中多實踐,提升自己的設計能力。 什么是設計模式? Christopher Alexander?說過:每一個模式描述了一個在我們周圍不斷重復發生的問題,以及該問題的解決方案的核心。這樣...
摘要:做前端開發已經好幾年了,對設計模式一直沒有深入學習總結過。今天第一天,首先來講策略模式。什么是策略模式四兄弟的經典設計模式中,對策略模式的定義如下定義一系列的算法,把它們一個個封裝起來,并且使它們可互相替換。 做前端開發已經好幾年了,對設計模式一直沒有深入學習總結過。隨著架構相關的工作越來越多,越來越能感覺到設計模式成為了我前進道路上的一個阻礙。所以從今天開始深入學習和總結經典的設計模...
摘要:很多人做開發,年后,都會感覺自己遇到瓶頸。公司的工作節奏又比較快,難有機會學習架構原理,也沒人教,所以這個時候,學習架構原理,擴展思維,對自己以后職業生涯尤為重要。 很多人做Java開發4,5年后,都會感覺自己遇到瓶頸。什么都會又什么都不會,如何改變困境,為什么很多人寫了7,8年還是一個碼農,工作中太多被動是因為不懂底層原理。公司的工作節奏又比較快,難有機會學習架構原理,也沒人教,所以...
摘要:面向對象常見的設計模式有策略模式模板方法觀察者模式責任鏈模式以及工廠模式,使用表達式函數式編程思維有助于避免面向對象開發中的那些固定代碼。 本文是一篇《Java 8實戰》的閱讀筆記,閱讀大約需要5分鐘。 有點標題黨,但是這確實是我最近使用Lambda表達式的感受。設計模式是過去的一些好的經驗和套路的總結,但是好的語言特性可以讓開發者不去考慮這些設計模式。面向對象常見的設計模式有策略模式...
摘要:這就是我和大佬的差距嗎看看別人是怎么做性能調優的性能調優后來的幾年里,我又陸續參與過物流電商游戲支付系統的研發,這些項目都存在一個共性,就是經常會運營一些大促以及搶購類活動。 先給大家講個故事吧。多年前我加入了一家大型互聯網公司,剛進入就以 996 標準,參與新品研發。公司業務發展急需互聯網產品,因此我們的時間很緊張,4 ...
閱讀 2880·2021-11-22 13:54
閱讀 3533·2021-11-16 11:44
閱讀 1374·2021-09-07 10:19
閱讀 1475·2019-08-29 17:30
閱讀 3202·2019-08-29 11:33
閱讀 3548·2019-08-26 12:18
閱讀 2892·2019-08-26 11:53
閱讀 1341·2019-08-26 10:47