iOS 設計模式之二十二(策略模式)

一、概念

1、策略模式的動機

? 雙十一是電商狂歡節,各種商品都會打折,而且打折的算法又是千奇百怪,比如滿多少錢打8折,滿多少錢減200塊,滿多少錢送一件等。在軟件開發中,實現某一個功能有多條途徑,每一條途徑對應一種算法,此時我們可以使用一種設計模式來實現靈活地選擇解決途徑,也能夠方便地增加新的解決途徑,這就是為了適應算法靈活性而產生的設計模式——策略模式

2、策略模式的定義

? 策略模式(Strategy Pattern):定義一系列算法類,將每一個算法封裝起來,并讓它們可以相互替換,策略模式讓算法獨立于使用它的客戶而變化,也稱為政策模式(Policy)。策略模式是一種對象行為型模式。

? 策略模式的主要目的是將算法的定義與使用分開,將算法的定義放在專門的策略類中,每一個具體策略類封裝了一種實現算法,使用算法的環境類針對抽象策略類進行編程,符合“依賴倒轉原則”。在出現新的算法時,只需要增加一個新的實現了抽象策略類的具體策略類即可。

3、策略模式的3個角色

1)Context(環境類):環境類是使用算法的角色,它在解決某個問題(即實現某個方法)時可以采用多種策略。在環境類中維持一個對抽象策略類的引用實例,用于定義所采用的策略。

2)Strategy(抽象策略類):它為所支持的算法聲明了抽象方法,是所有策略類的父類,它可以是抽象類或具體類,也可以是接口。環境類通過抽象策略類中聲明的方法在運行時調用具體策略類中實現的算法。

3)ConcreteStrategy(具體策略類):它實現了在抽象策略類中聲明的算法,在運行時,具體策略類將覆蓋在環境類中定義的抽象策略類對象,使用一種具體的算法實現某個業務處理。

4、結構圖
策略模式

二、示例

? 策略模式通常把一個系列的算法封裝到一系列具體策略類里面,作為抽象策略類的子類。環境類是需要使用算法的類,在一個系統中可以存在多個環境類,它們可能需要重用一些相同的算法。

1)先定義一個SortingStrategy協議,是排序算法協議,表示抽象策略類;

2)然后創建四個類BubbleSort、SelectionSort、InsertionSort和QuickSort,并遵循于SortingStrategy協議,表示具體策略類;

3)最后創建Context類,有一個strategy屬性,表示環境類。

SortingStrategy協議:

// 排序算法策略
@protocol SortingStrategy <NSObject>
- (NSArray *)sortingAlgorithmWithArray:(NSArray *)array; //聲明抽象算法
@end

typedef id<SortingStrategy> SortingStrategy;

BubbleSort、SelectionSort、InsertionSort和QuickSort類:

// BubbleSort 冒泡排序
@interface BubbleSort : NSObject<SortingStrategy>
@end
@implementation BubbleSort
- (NSArray *)sortingAlgorithmWithArray:(NSArray *)array {
    NSLog(@"使用冒泡排序算法");
    return [NSArray array]; //這里省略具體算法
}
@end

// SelectionSort 選擇排序
@interface SelectionSort : NSObject<SortingStrategy>
@end
@implementation SelectionSort
- (NSArray *)sortingAlgorithmWithArray:(NSArray *)array {
    NSLog(@"使用選擇排序算法");
    return [NSArray array]; //這里省略具體算法
}
@end

// InsertionSort 插入排序
@interface InsertionSort : NSObject<SortingStrategy>
@end
@implementation InsertionSort
- (NSArray *)sortingAlgorithmWithArray:(NSArray *)array {
    NSLog(@"使用插入排序算法");
    return [NSArray array]; //這里省略具體算法
}
@end

// QuickSort 快速排序
@interface QuickSort : NSObject<SortingStrategy>
@end
@implementation QuickSort
- (NSArray *)sortingAlgorithmWithArray:(NSArray *)array {
    NSLog(@"使用快速排序算法");
    return [NSArray array]; //這里省略具體算法
}
@end

Context類:

// 環境類:使用算法的角色
@interface Context : NSObject
@property(nonatomic, strong) SortingStrategy strategy; //維持一個對抽象策略類的引用
- (instancetype)initWithStrategy:(SortingStrategy)strategy;
- (NSArray *)sortWithArray:(NSArray *)array;
@end

@implementation Context
- (instancetype)initWithStrategy:(SortingStrategy)strategy {
    self = [super init];
    if (self) {
        _strategy = strategy;
    }
    return self;
}

- (NSArray *)sortWithArray:(NSArray *)array {
    return [self.strategy sortingAlgorithmWithArray:array]; //調用策略類中的算法
}
@end

運行代碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    SortingStrategy bubble = [BubbleSort new];
    Context *context1 = [[Context alloc] initWithStrategy:bubble];
    [context1 sortWithArray:@[@3, @1, @2]];
    
    SortingStrategy selection = [SelectionSort new];
    Context *context2 = [[Context alloc] initWithStrategy:selection];
    [context2 sortWithArray:@[@6, @8, @7]];
}

打印結果:

使用冒泡排序算法
使用選擇排序算法

三、總結

? 策略模式用于算法的自由切換和擴展,它是應用較為廣泛的設計模式之一。策略模式對應于解決某一問題的一個算法族,允許用戶從該算法族中任選一個算法來解決某一問題,同時可以方便地更換算法或者增加新的算法。只要涉及到算法的封裝、復用和切換都可以考慮使用策略模式。

1、優點

1、策略模式提供了對“開閉原則”的完美支持,用戶可以在不修改原有系統的基礎上選擇算法或行為,也可以靈活地增加新的算法或行為。

2、策略模式提供了管理相關的算法族的辦法。策略類的等級結構定義了一個算法或行為族,恰當使用繼承可以把公共的代碼移到抽象策略類中,從而避免重復的代碼。

3、策略模式提供了一種可以替換繼承關系的辦法。如果不使用策略模式,那么使用算法的環境類就可能會有一些子類,每一個子類提供一種不同的算法。但是,這樣一來算法的使用就和算法本身混在一起,不符合“單一職責原則”,決定使用哪一種算法的邏輯和該算法本身混合在一起,從而不可能再獨立演化;而且使用繼承無法實現算法或行為在程序運行時的動態切換。

4、策略模式提供了一種算法的復用機制,由于將算法單獨提取出來封裝在策略類中,因此不同的環境類可以方便地復用這些策略類。

2、缺點

1、客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。這就意味著客戶端必須理解這些算法的區別,以便適時選擇恰當的算法。換言之,策略模式只適用于客戶端知道所有的算法或行為的情況。

2、策略模式將造成系統產生很多具體策略類,任何細小的變化都將導致系統要增加一個新的具體策略類。

3、無法同時在客戶端使用多個策略類,也就是說,在使用策略模式時,客戶端每次只能使用一個策略類,不支持使用一個策略類完成部分功能后再使用另一個策略類來完成剩余功能的情況。

3、適用場景

1、一個系統需要動態地在幾種算法中選擇一種,那么可以將這些算法封裝到一個個的具體算法類中。

2、不希望客戶端知道復雜的、與算法相關的數據結構,在具體策略類中封裝算法與相關的數據結構,可以提高算法的保密性與安全性。

4、iOS應用舉例

? 在MVC模式中,控制器決定視圖對模型數據進行顯示的時機和內容。視圖本身知道如何繪圖,但需要控制器告訴它要顯示的內容。同一個視圖如果與不同的控制器合作,數據內容隨著不同控制器而不同,這個時候控制器就是視圖的策略。

Demo地址:iOS-Design-Patterns

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內容