流行框架源碼分析(15)-Strategy策略模式

主目錄見:Android高級進(jìn)階知識(這是總目錄索引)
?策略模式應(yīng)該說應(yīng)用也是非常廣泛,而且很容易使用挟裂。有的人可能用到了但是沒有意識到莫湘,那么我們今天會(huì)讓大家意識到而且能在特定的場景中使用到他哄尔。我們這里先來看看他的定義:

策略模式定義了一些列的算法振愿,并將每一個(gè)算法封裝起來,而且使它們還可以相互替換红选。策略模式讓算法獨(dú)立于使用它的客戶而獨(dú)立變換澜公。

這里的算法意思不是傳統(tǒng)的算法,其實(shí)就是一個(gè)action喇肋,就是一個(gè)獨(dú)立的執(zhí)行邏輯坟乾。策略模式可以獨(dú)立出來這些邏輯,然后在特定場景選擇特定的執(zhí)行邏輯蝶防。接著我們來看看他的UML類圖:


策略模式

角色介紹:

  • IStrategy:策略接口甚侣,定義了各個(gè)策略的公共接口
  • ConcreteStrategy:具體的策略類,里面實(shí)現(xiàn)了策略接口中的策略方法慧脱。
  • Context:用來操作各個(gè)策略的渺绒,利用具體的策略類進(jìn)行各種策略執(zhí)行。

一.目標(biāo)

我們今天的目標(biāo)跟之前講的設(shè)計(jì)模式也是一樣菱鸥,我們在明白別人使用的場景的時(shí)候自己遇到的時(shí)候也能利用起來宗兼。所以今天目標(biāo)也同樣是:
1.學(xué)會(huì)策略模式在什么場景下使用;
2.能在自己編寫框架的時(shí)候用上這個(gè)設(shè)計(jì)模式氮采。

二.模式解析

首先也是我們這里先假設(shè)一個(gè)場景:我們大學(xué)編程的時(shí)候殷绍,遇到一個(gè)編程題目解不出來,那么這時(shí)候有幾種情況可以解決鹊漠。一個(gè)是查看答案主到,一個(gè)是求教同學(xué),一個(gè)是請教老師躯概。那我們平常寫代碼可能是這樣:

public class StrategyPatternMain {
    
    enum Strategy{
        CHECK_ANSWER,SEARCH_HELP,CONSULT_TEACHER
    }
    
    private Strategy strategy;
    public StrategyPatternMain(Strategy strategy){
        super();
        this.strategy = strategy;
    }
    
    public void doAction(){
        switch (strategy) {
        case CHECK_ANSWER:
            System.out.println("查看答案");
            break;
        case SEARCH_HELP:
            System.out.println("請教同學(xué)");
            break;
        case CONSULT_TEACHER:
            System.out.println("請教老師");
            break;
        default:
            break;
        }
    }

    public static void main(String[] args) {
        StrategyPatternMain homeWorkStrategy = new StrategyPatternMain(Strategy.SEARCH_HELP);
        homeWorkStrategy.doAction();
        
        StrategyPatternMain homeWorkStrategy2 = new StrategyPatternMain(Strategy.CHECK_ANSWER);
        homeWorkStrategy2.doAction();
        
        StrategyPatternMain homeWorkStrategy3 = new StrategyPatternMain(Strategy.CONSULT_TEACHER);
        homeWorkStrategy3.doAction();

    }
}

可以看到登钥,完美有沒有,你來一個(gè)新的方式我這邊可以再增加一個(gè)case娶靡,靈活有沒有牧牢。然后最后你想到方法越來越多,這個(gè)類就被修改了無數(shù)遍姿锭,代碼就是一坨一坨的塔鳍,這時(shí)候你想,不行呀呻此,我應(yīng)該讓他可以組裝呀轮纫,而且不影響原有的代碼。那么策略模式就蹦出來了焚鲜。

1.策略模式

我們這里解決這個(gè)擴(kuò)展困難問題掌唾,我們這里引入策略模式放前,首先我們先來看看策略接口:

public interface IStrategy {
    void doAction();
}

這個(gè)策略接口類很簡單,就是一個(gè)方法郑兴,然后我們來看看幾個(gè)具體策略類:

public class CheckAnswer implements IStrategy {

    @Override
    public void doAction() {
        System.out.println("查看答案");
    }
}

public class SearchHelp implements IStrategy {

    @Override
    public void doAction() {
        System.out.println("請教同學(xué)");
    }
}

public class ConsultTeacher implements IStrategy {

    @Override
    public void doAction() {
        System.out.println("請教老師");
    }
}

我們看到幾個(gè)策略類也是非常簡單的犀斋,就是簡單地執(zhí)行各自的打印動(dòng)作贝乎。然后我們看下Context類:

public class Context {
    private IStrategy strategy;
    
    public void setStrategy(IStrategy strategy){
        this.strategy = strategy;
    }
    
    public void doAction(){
        strategy.doAction();
    }
}

我們看到這里面持有了一個(gè)策略類的引用情连,然后在方法里面調(diào)用相應(yīng)的action。我們看下這個(gè)怎么使用:

        IStrategy checkAnswer = new CheckAnswer();
        IStrategy searchHelp = new SearchHelp();
        IStrategy consultTeacher = new ConsultTeacher();
        
        Context context = new Context();
        context.setStrategy(checkAnswer);
        context.doAction();
        
        context.setStrategy(searchHelp);
        context.doAction();
        
        context.setStrategy(consultTeacher);
        context.doAction();

我們看到這邊如果增加了尋找解決問題的方法览效,我們只要增加一個(gè)具體策略類却舀,然后在使用的時(shí)候,設(shè)置進(jìn)去就可以了锤灿,這樣的話面對擴(kuò)展就非常地方便挽拔。這也是我們?yōu)樯兑褂眠@個(gè)模式的原因。

2.屬性動(dòng)畫中策略模式的使用

屬性動(dòng)畫中的插值器(Interpolator)和估值器(Evaluator)的使用就是用的策略模式但校,我們先來看下插值器螃诅。我們先來看下之前寫過一篇[屬性動(dòng)畫基礎(chǔ)用法]中有個(gè)屬性用法是這樣的:

  Point endPoint = new Point(getWidth() - RADIUS,getHeight() - RADIUS);
        ValueAnimator valueAnimator = ValueAnimator.ofObject(new PointEvaluator(),currentPoint,endPoint);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                currentPoint = (Point) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
//這里設(shè)置了插值器
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.setDuration(2000);
        valueAnimator.start();

我們看到這里設(shè)置了具體的插值器,那么我們來分析下這里面的策略模式的各個(gè) 角色状囱,首先就是Context角色术裸,這個(gè)很明顯就是ValueAnimator,我們看下他的setInterpolator方法:

  @Override
    public void setInterpolator(TimeInterpolator value) {
        if (value != null) {
            mInterpolator = value;
        } else {
            mInterpolator = new LinearInterpolator();
        }
    }

可以看到這個(gè)里面設(shè)置了具體插值器的引用亭枷。然后我們看看具體插值器也就是具體策略類的實(shí)現(xiàn):

@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {

    public LinearInterpolator() {
    }

    public LinearInterpolator(Context context, AttributeSet attrs) {
    }

    public float getInterpolation(float input) {
        return input;
    }

    /** @hide */
    @Override
    public long createNativeInterpolator() {
        return NativeInterpolatorFactoryHelper.createLinearInterpolator();
    }
}

我們看到這個(gè)具體插值器繼承了BaseInterpolator 并且實(shí)現(xiàn)了NativeInterpolatorFactory袭艺。這里的BaseInterpolator 實(shí)際又實(shí)現(xiàn)了Interpolator,然后Interpolator又實(shí)現(xiàn)了TimeInterpolator:

public interface TimeInterpolator {
    float getInterpolation(float input);
}

所以TimeInterpolator 我們這里可以當(dāng)做抽象插值器類也就是抽象策略類叨粘』啵看到這里我們已經(jīng)把每個(gè)策略模式的角色都分出來了。其實(shí)是非常簡單的升敲,但是達(dá)到的效果確實(shí)符合程序優(yōu)秀設(shè)計(jì)的思想答倡。至于估值器其實(shí)也是類似的,這里就不舉那么多例子了驴党,大家看懂就可以瘪撇。其實(shí)在Glide里面大家設(shè)置緩存策略的時(shí)候也會(huì)用到策略設(shè)計(jì)模式,大家有興趣可以自己也看看鼻弧。
總結(jié):策略模式使用簡單设江,場景也非常多,記住遇到if-else攘轩,switch特別多的場景叉存,同時(shí)程序后面可能會(huì)變化,條件會(huì)增加度帮。這時(shí)候往往就是策略模式派上用場的時(shí)候歼捏,所以我們平常用設(shè)計(jì)模式的時(shí)候要多想多用稿存。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市瞳秽,隨后出現(xiàn)的幾起案子瓣履,更是在濱河造成了極大的恐慌,老刑警劉巖练俐,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袖迎,死亡現(xiàn)場離奇詭異,居然都是意外死亡腺晾,警方通過查閱死者的電腦和手機(jī)燕锥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悯蝉,“玉大人归形,你說我怎么就攤上這事”怯桑” “怎么了暇榴?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蕉世。 經(jīng)常有香客問我蔼紧,道長,這世上最難降的妖魔是什么讨彼? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任歉井,我火速辦了婚禮,結(jié)果婚禮上哈误,老公的妹妹穿的比我還像新娘哩至。我一直安慰自己,他們只是感情好蜜自,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布菩貌。 她就那樣靜靜地躺著,像睡著了一般重荠。 火紅的嫁衣襯著肌膚如雪箭阶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天戈鲁,我揣著相機(jī)與錄音仇参,去河邊找鬼。 笑死婆殿,一個(gè)胖子當(dāng)著我的面吹牛诈乒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播婆芦,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼怕磨,長吁一口氣:“原來是場噩夢啊……” “哼喂饥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肠鲫,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤员帮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后导饲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體捞高,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年帜消,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了棠枉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡泡挺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出命浴,到底是詐尸還是另有隱情娄猫,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布生闲,位于F島的核電站媳溺,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碍讯。R本人自食惡果不足惜悬蔽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捉兴。 院中可真熱鬧蝎困,春花似錦、人聲如沸倍啥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虽缕。三九已至始藕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氮趋,已是汗流浹背伍派。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剩胁,地道東北人诉植。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像摧冀,于是被迫代替她去往敵國和親倍踪。 傳聞我的和親對象是個(gè)殘疾皇子系宫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)建车,斷路器扩借,智...
    卡卡羅2017閱讀 134,716評論 18 139
  • 本文首發(fā)于個(gè)人博客:Lam's Blog - 談?wù)?3種設(shè)計(jì)模式在Android源碼及項(xiàng)目中的應(yīng)用,文章由Mark...
    格子林ll閱讀 4,654評論 1 105
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,331評論 25 707
  • 我有個(gè)好朋友缤至,她算是個(gè)活在夢幻里的人潮罪,喜歡笑,敢于哭领斥,愛熱鬧嫉到。高三時(shí)候,她和一個(gè)男生交往月洛。那個(gè)男生是她之前最...
    金污一閱讀 263評論 0 0
  • 這幅畫大家一定很陌生何恶,容喜歡歷史的我介紹一下: 新郎是光緒皇帝,清朝的第十一位皇帝嚼黔;新娘是葉赫那拉·靜芬细层,...
    帥梅香茗閱讀 1,252評論 5 2