此文章全是文字宴凉,但是不長誊锭,看上去有點枯燥,還請保持耐心弥锄。
策略模式,很多人會忘記的一個模式,但是是我們平時開發(fā)中用到的最多的籽暇,我個人而言温治,我認(rèn)為多態(tài)的使用,就是策略模式的最好應(yīng)用戒悠。
定義
策略模式定義了一系列的算法熬荆,并將每一個算法封裝起來,而且使它們還可以互相替換绸狐。策略模式讓算法獨立于使用它的客戶而獨立變化卤恳。
通過建立抽象,將不同的策略構(gòu)建成一個具體的策略實現(xiàn)寒矿,通過不同的策略實現(xiàn)算法替換突琳。在簡化邏輯、結(jié)構(gòu)的同時符相,增強了系統(tǒng)的可讀性拆融、穩(wěn)定性、可擴展性啊终,這對于較為復(fù)雜的業(yè)務(wù)邏輯顯得更為直觀镜豹,擴展也更為方便。
使用場景
在軟件開發(fā)中常常遇到這樣的情況:實現(xiàn)某一個功能可以有多種算法或者策略蓝牲,我們根據(jù)事件情況選擇不同的算法或者策略來完成該功能趟脂。例如,排序算法例衍,可以使用插入排序散怖、歸并排序、冒泡排序等肄渗。
這對這種情況镇眷,一個常規(guī)的方法是將多種算法寫在一個類中。例如翎嫡,需要提供多種排序算法欠动。可以將這些算法寫到一個 類中惑申,每一個方法對應(yīng)一個具體的排序算法具伍;當(dāng)然,也可以將這些排序算法封裝到一個統(tǒng)一的方法中圈驼,通過 if….else… 或者 case 等條件判斷語句來選擇具體的算法人芽。這兩種實現(xiàn)方式都可以稱為硬編碼。然而绩脆,當(dāng)很多個算法集中在一個類中時萤厅,這個類就會變得臃腫橄抹,這個類的維護成本也會變高,在維護時也更容易引發(fā)錯誤惕味。如果我們需要增加一種新的排序算法楼誓,需要修改封裝算法類的源代碼。這就明顯違反了我們前面博客中所說的 SOLID 原則中的 開閉原則和單一職責(zé)原則名挥。
如果將這些算法或者策略抽象出來疟羹,提供一個統(tǒng)一的接口,不同的算法或者策略有不同的實現(xiàn)類禀倔,這樣在程序客戶端就可以通過注入不同的實現(xiàn)對象來實現(xiàn)算法或者策略的動態(tài)替換榄融,這種模式的可擴展性、可維護性也就更高救湖,也就是我們接下來要說的策略模式愧杯。
使用場景總結(jié)
- 針對同一類型問題的多種處理方式,僅僅是具體行為有差別時捎谨。
- 需要安全地封裝多種同一類型的操作時民效。
- 出現(xiàn)同一抽象類有多個子類,而又需要使用if-else 或者 switch-case 來選擇具體子類時涛救。
如何實現(xiàn)
1.定義接口A畏邢,想好封裝
2.implement A接口 實現(xiàn)B
3.多態(tài)使用(這么一說,我仿佛在說 java基礎(chǔ)之多態(tài))
class B implement A{
}
class M{
A a;
public void setFunc(A b){
a = b;
}
}
源碼應(yīng)用
其實這個是個很簡單的設(shè)計模式检吆,應(yīng)用很多舒萎,我們來看看Android源碼中有什么經(jīng)典應(yīng)用吧。
TimeInterpolator 時間插值器
我們來看一個插值器源碼
/**
* An interpolator where the rate of change is constant
*
*/
@HasNativeInterpolator
public class LinearInterpolator implements Interpolator, NativeInterpolatorFactory {
public LinearInterpolator() {
}
public LinearInterpolator(Context context, AttributeSet attrs) {
}
public float getInterpolation(float input) {
return input;
}
/** @hide */
@Override
public long createNativeInterpolator() {
return NativeInterpolatorFactoryHelper.createLinearInterpolator();
}
}
每個動畫都有自己的默認(rèn)插值器, 而通過抽象出插值器接口(最新版本的源碼又改了)蹭沛,然后我們可以通過setInterpolator去改變它
這樣大大增加了類的功能上的擴展性
animtorAlpha.setInterpolator(new LinearInterpolator());
當(dāng)我們調(diào)用ssetInterpolator時臂寝,發(fā)生了哪些事情呢?
public class ValueAnimator extends Animator{
//插值器也有自己的默認(rèn)初始值
private TimeInterpolator mInterpolator = sDefaultInterpolator;
// The time interpolator to be used if none is set on the animation
private static final TimeInterpolator sDefaultInterpolator =
new AccelerateDecelerateInterpolator();
//設(shè)置插值器
@Override
public void setInterpolator(TimeInterpolator value) {
if (value != null) {
mInterpolator = value;
} else {
mInterpolator = new LinearInterpolator();
}
}
}
當(dāng)我們調(diào)用時摊灭,直接替換了TimeInterpolator咆贬。無需干其他事情,我們自己寫多種復(fù)用的自定義view啊帚呼,window啊掏缎,都可以借鑒這樣的寫法。
小小總結(jié)
總結(jié)
策略模式主要用來分離算法煤杀,在相同的行為抽象下有不同的具體實現(xiàn)策略眷蜈。這個模式很好地演示了開閉原則,也就是定義抽象沈自,注入不同的實現(xiàn)酌儒,從而達(dá)到很好的可擴展性。
優(yōu)點
- 結(jié)構(gòu)清晰明了枯途,使用簡單直觀忌怎;
- 耦合度相對而言較低籍滴,擴展方便;
- 操作封裝也更為徹底呆躲,數(shù)據(jù)更為安全异逐。
缺點:
- 隨著策略的增加捶索,子類也會變得繁多插掂。
謝謝大家閱讀,如有幫助腥例,來個喜歡或者關(guān)注吧辅甥!
本文作者:Anderson/Jerey_Jobs
簡書地址:[Anderson大碼渣][1]
github地址:[Jerey_Jobs][2]
[1]: http://www.reibang.com/users/016a5ba708a0/latest_articles
[2]: https://github.com/Jerey-Jobs