Android 設(shè)計模式之狀態(tài)模式

在日常開發(fā)過程中時常需要用到設(shè)計模式市怎,但是設(shè)計模式有23種拧篮,如何將這些設(shè)計模式了然于胸并且能在實際開發(fā)過程中應(yīng)用得得心應(yīng)手呢隐岛?和我一起跟著《Android源碼設(shè)計模式解析與實戰(zhàn)》一書邊學(xué)邊應(yīng)用吧!

設(shè)計模式系列文章

今天我們要講的是狀態(tài)模式(State模式)


定義

當一個對象的內(nèi)在狀態(tài)改變時允許改變其行為尖昏,這個對象看起來像是改變了其類

使用場景

  • 一個對象的行為取決于它的狀態(tài)仰税,并且它必須在運行時根據(jù)狀態(tài)改變它的行為
  • 代碼中包含大量與對象狀態(tài)有關(guān)的條件語句,例如抽诉,一個操作中含有龐大的多分支語句(if-else或switch-case)陨簇,且這些分支依賴于該對象的狀態(tài)

使用例子

  • 最常見的應(yīng)用是用戶登錄系統(tǒng)

實現(xiàn)

3大角色

  • 環(huán)境類:定義客戶端感興趣的接口,維護一個抽象狀態(tài)類的子類的實例掸鹅,這個實例定義了對象當前狀態(tài)
  • 抽象狀態(tài)類或狀態(tài)接口:定義一個或一組接口塞帐,表示該狀態(tài)下的行為
  • 具體狀態(tài)類:每個具體狀態(tài)類實現(xiàn)抽象狀態(tài)類中定義的接口,從而達到不同狀態(tài)下的不同行為

實現(xiàn)的要點

  • 把不同狀態(tài)下的行為抽象成共同的接口到抽象狀態(tài)類中
  • 根據(jù)不同的狀態(tài)巍沙,具體的狀態(tài)類實現(xiàn)抽象狀態(tài)類中的接口葵姥,從而實現(xiàn)不同的行為
  • 環(huán)境類,也就是對外提供服務(wù)的類通過依賴抽象狀態(tài)類來實現(xiàn)具體的行為句携,同時也達到與具體狀態(tài)類的解耦

實現(xiàn)方式

下面我們以日常開發(fā)中的登錄功能來簡單應(yīng)用下狀態(tài)模式

  • 在登錄模塊中一般我們會根據(jù)用戶是否登錄狀態(tài)而有不同的操作榔幸,這里簡單模擬2個操作,轉(zhuǎn)發(fā)和評論
public interface UserState {

    /**
     * 轉(zhuǎn)發(fā)
     *
     * @param context
     */
    public void forward(Context context);

    /**
     * 評論
     *
     * @param context
     */
    public void comment(Context context);
}
  • 登錄狀態(tài)矮嫉,調(diào)用轉(zhuǎn)發(fā)和評論直接簡單地彈出個Toast
public class LoginedState implements UserState {

    @Override
    public void forward(Context context) {
        Toast.makeText(context, "轉(zhuǎn)發(fā)成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void comment(Context context) {
        Toast.makeText(context, "評論成功", Toast.LENGTH_SHORT).show();

    }
}
  • 未登錄狀態(tài)削咆,調(diào)用轉(zhuǎn)發(fā)和評論跳轉(zhuǎn)到登錄頁面,這里直接簡單地彈出登錄的提示
public class LogoutState implements UserState {

    @Override
    public void forward(Context context) {
        Toast.makeText(context, "未登錄蠢笋,跳轉(zhuǎn)到登錄頁面", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void comment(Context context) {
        Toast.makeText(context, "未登錄拨齐,跳轉(zhuǎn)到登錄頁面", Toast.LENGTH_SHORT).show();

    }
}

  • 根據(jù)不同的狀態(tài)表現(xiàn)不一樣的行為。下面我們看看對外提供服務(wù)的環(huán)境類
public class LoginContext {

    /**
     * 用戶狀態(tài)昨寞,默認為登錄狀態(tài)
     */
    UserState userState = new LoginedState();

    /**
     * 單例
     */
    static LoginContext loginContext = new LoginContext();

    private LoginContext() {

    }

    public LoginContext getLoginContext() {
        return loginContext;
    }

    public void setUserState(UserState userState) {
        this.userState = userState;
    }

    public void forward(Context context) {
        userState.forward(context);
    }

    public void comment(Context context) {
        userState.comment(context);
    }
}

  • 以上的環(huán)境類的實現(xiàn)中瞻惋,默認狀態(tài)設(shè)置為登錄狀態(tài),這個可以根據(jù)實際需要來定援岩。下面我們看看怎么調(diào)用
//因為默認是登錄狀態(tài)歼狼,所以可以直接調(diào)用轉(zhuǎn)發(fā)功能
LoginContext.getLoginContext().forward(MainActivity.this)

//注銷登錄,也就是登錄狀態(tài)改為未登錄
LoginContext.getLoginContext().setUserState(new LogoutState());

//注銷登錄了以后再調(diào)用轉(zhuǎn)發(fā)或是評論功能享怀,執(zhí)行的就會是彈出登錄提示
LoginContext.getLoginContext().forward(MainActivity.this)
  • 通過以上的例子我們就簡單地實現(xiàn)了狀態(tài)模式的應(yīng)用啦

通過上面的例子我們可以看出羽峰,狀態(tài)模式把對象的不同狀態(tài)下的行為封裝起來,并與對象的狀態(tài)聯(lián)系在一起。對象的狀態(tài)改變了梅屉,對象的行為也會改變值纱。在上面的例子中就是登錄的狀態(tài)LoginContext中的UserState狀態(tài)不一樣,執(zhí)行的行為履植,比如轉(zhuǎn)發(fā)功能就不一樣

狀態(tài)模式和策略模式

狀態(tài)模式和策略模式的結(jié)構(gòu)幾乎完全一樣计雌,但它們的目的、本質(zhì)卻完全不一樣玫霎。狀態(tài)模式的行為是平行的凿滤、不可替換的,策略模式的行為是彼此獨立庶近、可相互替換的翁脆。用一句話來表述,狀態(tài)模式把對象的行為包裝在不同的狀態(tài)對象里鼻种,每一個狀態(tài)對象都有一個共同的抽象狀態(tài)基類反番。狀態(tài)模式的意圖是讓一個對象在其內(nèi)部狀態(tài)發(fā)生改變的時候,其行為也隨之改變

總結(jié)

  • 狀態(tài)模式的關(guān)鍵點在于不同的狀態(tài)下對于同一行為有不同的響應(yīng)叉钥,這其實就是一個將if-else用多態(tài)來實現(xiàn)的具體實例
  • 狀態(tài)模式將所有與一個特定狀態(tài)相關(guān)的行為都放入一個狀態(tài)對象中罢缸,它提供了一個更好的方法來組織與特定狀態(tài)相關(guān)的代碼,將繁瑣的狀態(tài)判斷轉(zhuǎn)換成結(jié)構(gòu)清晰的狀態(tài)類族投队,在避免代碼膨脹的同時也保證了可擴展性和可維護性

              歡迎關(guān)注我的微信公眾號枫疆,期待與你一起學(xué)習(xí),一起交流敷鸦,一起成長息楔!
AntDream
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市扒披,隨后出現(xiàn)的幾起案子值依,更是在濱河造成了極大的恐慌,老刑警劉巖碟案,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愿险,死亡現(xiàn)場離奇詭異,居然都是意外死亡价说,警方通過查閱死者的電腦和手機辆亏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來熔任,“玉大人褒链,你說我怎么就攤上這事唁情∫商Γ” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵甸鸟,是天一觀的道長惦费。 經(jīng)常有香客問我兵迅,道長,這世上最難降的妖魔是什么薪贫? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任恍箭,我火速辦了婚禮,結(jié)果婚禮上瞧省,老公的妹妹穿的比我還像新娘扯夭。我一直安慰自己,他們只是感情好鞍匾,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布交洗。 她就那樣靜靜地躺著,像睡著了一般橡淑。 火紅的嫁衣襯著肌膚如雪构拳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天梁棠,我揣著相機與錄音置森,去河邊找鬼。 笑死符糊,一個胖子當著我的面吹牛凫海,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播濒蒋,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼盐碱,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沪伙?” 一聲冷哼從身側(cè)響起瓮顽,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎围橡,沒想到半個月后暖混,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡翁授,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年拣播,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片收擦。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡贮配,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出塞赂,到底是詐尸還是另有隱情泪勒,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站圆存,受9級特大地震影響叼旋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沦辙,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一夫植、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧油讯,春花似錦详民、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至诀紊,卻和暖如春谒出,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背邻奠。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工笤喳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碌宴。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓杀狡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贰镣。 傳聞我的和親對象是個殘疾皇子呜象,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,730評論 25 707
  • 設(shè)計模式匯總 一、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用碑隆、多...
    MinoyJet閱讀 3,919評論 1 15
  • 本文首發(fā)于個人博客:Lam's Blog - 談?wù)?3種設(shè)計模式在Android源碼及項目中的應(yīng)用恭陡,文章由Mark...
    格子林ll閱讀 4,632評論 1 105
  • 親愛的DD:你好! 每天晚上睡覺前上煤,都是媽媽給你講繪本故事的快樂時光休玩。最近,你最喜歡的繪本是《小豬佩奇》劫狠,一套共有...
    Leice閱讀 174評論 0 0
  • 什么時候呢 開始為了生活而生活 為了工作而工作 恐懼 將就 妥協(xié) 忙忙碌碌卻碌碌無為 生活成了一部默聲的黑白影片 ...
    記憶之城SINCE1994閱讀 290評論 0 0