1.策略模式簡介
??策略模式(Strategy Pattern),是行為型模式之一(設計模式分類:http://www.itdecent.cn/p/18fee11deac9)。
??在軟件開發(fā)中常常遇到這樣的情況:實現某一個功能可以有多種算法或者策略,我們根據實際情況選擇不同的算法或者策略來完成該功能。例如,排序算法,可以使用插入排序、歸并排序、冒泡排序等。
??針對這種情況,一種常規(guī)的方法是將多種算法寫在一個類中。例如,需要提供多種排序算法,可以將這些算法寫到一個類中,每一個方法對應一個具體的排序算法;當然,也可以將這些排序算法封裝在一個統(tǒng)一的方法中,通過if...else... 或者case等條件判斷語句來選擇具體的算法。這兩種實現方法我們都可以稱為硬編碼。然而,當很多個算法集中在一個類中,這個類就會變得臃腫,這個類的維護成本會變高,在維護時也更容易引發(fā)錯誤。如果我們增加一種新的排序算法,需要修改封裝算法類的源代碼。這就明顯違反了我們所說的OCP(開閉)原則和單一職責原則。(OCP:軟件中的對象(類、模塊、函數等)應該對于擴展是開放的,但是對于修改是封閉的。)
??如果將這些算法或者策略抽象出來,提供一個統(tǒng)一的接口,不同的算法或者策略有不同的實現類(類肯定是變多了),這樣在程序客戶端就可以通過注入不同的實現對象來實現算法或者策略的動態(tài)替換,這種模式的可擴展性、可維護性也就更高,也就是我們所說的策略模式。-《Android源碼設計模式解析與實戰(zhàn)》
2策略模式定義
??策略模式定義了一系列算法,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。-《Android源碼設計模式解析與實戰(zhàn)》
??面向對象軟件設計中,我們可以把相關算法分離為不同的類,成為策略。與這種做法有關的一種設計模式稱為策略模式。
3.策略模式的使用場景
3.1 針對同一類型問題的多種處理方式,僅僅只是具體行為有差別時。
3.2需要安全地封裝多種同一類型的操作時。
3.3出現統(tǒng)一抽象類有多個子類,而又需要使用if-else 或者 switch-case 來選擇具體子類時。
4.策略模式的UML圖

5.策略模式 角色劃分
角色一:Context 用于操作策略的上下文環(huán)境 場景類的對象配置有一個具體策略對象的實例,場景對象使用策略接口調用有具體策略類定義的算法。
角色二:Stragety 抽象策略
角色三:ConcreteStragety 具體策略
6.Demo 實踐
??假設應用程序中需要用UITextField以接受用戶的輸入,然后要在應用程序的處理中使用這個輸入值。應用程序有個文字輸入框,只接受字母,即a-z或A-Z,還有個輸入框只接受數值型的值,即0~9。為了保證每個字段的輸入有效,需要在用戶結束文本框的編輯時做些驗證。
??這個時候我們可以把數據驗證放大UITextField的委托方法textFieldDidEndEditing:之中。UITextfield的實例每當失去焦點時會調用這個方法。如果不用策略模式,代碼通常會寫成下面的樣子:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if (textField == letterTextField) {
//驗證是否是字母
} else if (textField == numberTextField){
//驗證是否是數字
} else if ...
}
??要是有更多不同類型的文本框,條件語句還會繼續(xù)下去,代碼越來越臃腫,難以維護。如果能去掉這些條件語句,代碼會更易管理,將來對代碼的維護也會容易得多。(如果代碼中有很多條件語句,就可能意味著需要把它們重構成各種策略模式)
??所以現在的目標是把這些驗證檢查提到各種策略類中,這樣它們就能在委托或者其他方法中重用。每個驗證都從文本框取出輸入值,然后根據所需的策略進行驗證,最后返回個BOOL值; 如果驗證失敗,還會返回一個NSError實例。返回的NSError可以解釋失敗的原因。
Demo的UML圖如下:

這里不把接口聲明為協議,而是聲明為抽象基類。抽象基類更適合解決這種問題,因為它更容易重構各種具體策略子類的某些共同行為。
使用策略模式后客戶端代碼的樣子:
- (void)textFieldDidEndEditing:(UITextField *)textField
{
if ([textField isKindOfClass:[CustomTextField class]]) {
[(CustomTextField*)textField validate];
}
}
重要的事情說三遍,一定要看Demo,一定要看Demo,一定要看Demo。
Demo地址:https://github.com/zhiyoukaifa/StrategyPatternDemo
zs20190115+ Demo優(yōu)化: https://github.com/zhiyoukaifa/StrategyPatternDemo2
參考書籍:
《Objective-C編程之道 iOS設計模式解析》
《Android源碼設計模式解析與實戰(zhàn)》