引序:還記不記得這樣的場(chǎng)景:把一堆算法塞到同一段代碼中位谋,然后使用if-else或switch-case條件語(yǔ)句來(lái)決定要使用哪個(gè)算法帆疟?這些算法可能是一堆相似的類(lèi)函數(shù)或方法宦棺,用以解決相關(guān)的問(wèn)題沾鳄。比如,一個(gè)驗(yàn)證輸入數(shù)據(jù)的例程响疚,數(shù)據(jù)本身可以是任何數(shù)據(jù)類(lèi)型(如NSString鄙信、CGFloat等),每種數(shù)據(jù)類(lèi)型需要不同的驗(yàn)證算法稽寒。如果能把每個(gè)算法封裝成一個(gè)對(duì)象扮碧,那么就能消除根據(jù)數(shù)據(jù)類(lèi)型決定使用什么算法的一堆if-else或switch-case語(yǔ)句。
一、何為策略模式
我們把相關(guān)算法分離為不同的類(lèi)慎王,稱(chēng)為策略模式蚓土。策略模式:定義一系列算法,把它們一個(gè)個(gè)封裝起來(lái)赖淤,并且使它們可相互替換蜀漆。本模式使得算法可獨(dú)立于使用它的客戶(hù)端而變化。
二咱旱、組成
—抽象策略角色: 策略類(lèi)确丢,通常由一個(gè)接口或者抽象類(lèi)實(shí)現(xiàn)。
—具體策略角色:包裝了相關(guān)的算法和行為吐限。
—環(huán)境角色:持有一個(gè)策略類(lèi)的引用鲜侥,最終給客戶(hù)端調(diào)用。
策略模式中一個(gè)關(guān)鍵角色是策略類(lèi)诸典,他為所有支持或相關(guān)的算法聲明了一個(gè)共同接口描函。另外,還有使用策略接口來(lái)實(shí)現(xiàn)相關(guān)算法的具體策略類(lèi)狐粱。 ?場(chǎng)景類(lèi)(context)的對(duì)象配置有一個(gè)具體策略對(duì)象的實(shí)例舀寓,場(chǎng)景對(duì)象使用策略接口調(diào)用由具體策略類(lèi)定義的算法。他們的靜態(tài)關(guān)系如圖:
三肌蜻、何時(shí)使用策略模式互墓。?
@:一個(gè)類(lèi)在其操作中,使用多個(gè)條件語(yǔ)句來(lái)定義許多行為蒋搜,我們可以把相關(guān)的條件分支移到它們自己的策略類(lèi)中篡撵。?
@:需要算法的各種變體。?
@:需要避免把復(fù)雜的齿诞、與算法相關(guān)的數(shù)據(jù)結(jié)構(gòu)暴漏給客戶(hù)端酸休。
四骂租、在UITextfeild 中應(yīng)用驗(yàn)證策略
我們用一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明以下祷杈,策略模式是怎么使用的。假設(shè)有兩個(gè)UITextField渗饮,一個(gè)UITextField只能輸入字母但汞,另一個(gè)UITextField只能輸入數(shù)字,為了確保輸入的有效性互站,我們需要在用戶(hù)結(jié)束文本框的編輯時(shí)做下驗(yàn)證私蕾。我們把數(shù)據(jù)驗(yàn)證放在代理方法textFieldDidEndEdting中。
如果不使用策略模式胡桃,我們的代碼會(huì)寫(xiě)成這樣:
(void)textFieldDidEndEditing:(UITextField *)textField {?
if (textField == self.numberTF) {?
// 驗(yàn)證其值只包含數(shù)字
}else if (textField == self.alphaTF) {?
// 驗(yàn)證其值只包含字母
} else if( ? ){
}?else if( ? ){
...
}?
要是有更多不同類(lèi)型的文本框踩叭,條件語(yǔ)句還會(huì)繼續(xù)下去。如果能去掉這些條件語(yǔ)句,代碼會(huì)更容易管理容贝,將來(lái)對(duì)代碼的維護(hù)也會(huì)容易許多自脯。
現(xiàn)在的目標(biāo)是把這些驗(yàn)證檢查提到各種策略類(lèi)中,這樣他們就能在代理方法和其他方法之中重用斤富。