淺析狀態(tài)機設(shè)計模式

背景

在需求開發(fā)的過程中拍鲤,經(jīng)常會遇到根據(jù)不同的情況作出不同的處理之景。最直接的就是if...else...。
當(dāng)場景特別復(fù)雜時肯夏,判斷if就有些力不從心了。加一個場景需要修改大量的代碼犀暑,這不是一個很好的做法。程序的擴展性特別薄弱烁兰。

舉個栗子:
當(dāng)我們給朋友手機打電話的時候耐亏,朋友的手機就可能出現(xiàn)幾種情況:用戶開機,用戶關(guān)機沪斟,用戶欠費停機广辰,用戶銷戶等。不同的場景產(chǎn)生不同的結(jié)果主之。

狀態(tài)模式

狀態(tài)模式就是用來解決大量不同場景不同行為的模式择吊。
狀態(tài)模式:允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為,對象看起來似乎修改了它的類槽奕。

狀態(tài)模式包含的角色

  • Context:環(huán)境類
  • State:抽象狀態(tài)類
  • ConcreteState:具體狀態(tài)類
模式結(jié)構(gòu)

示例

日常生活中几睛,我們遇到的最多的帶有狀態(tài)的對象應(yīng)該就是電梯了,電梯有開門粤攒,關(guān)門所森,運行,停止?fàn)顟B(tài)夯接。

public interface ILift {
    // 電梯門開狀態(tài)
    public void open();

    // 電梯關(guān)門狀態(tài)
    public void close();

    // 電梯移動狀態(tài)
    public void run();

    // 電梯停止?fàn)顟B(tài)
    public void stop();
}

電梯的接口有了焕济,我們可以來看下實現(xiàn)類:

public class Lift implements ILift {
    public void open() {
        System.out.println("lift is opening");
    }

    public void close() {
        System.out.println("lift is closed");
    }

    public void run() {
        System.out.println("lift run up or down");
    }

    public void stop() {
        System.out.println("lift stopped");
    }
}

下面就是電梯類怎么調(diào)用的問題?我們知道狀態(tài)之間是有一定的前提條件的盔几,也就是說狀態(tài)不能隨意轉(zhuǎn)化晴弃。

如果電梯處于open狀態(tài),那它下一個必然是close關(guān)門狀態(tài)逊拍,而不能是run狀態(tài)上鞠;當(dāng)電梯是close狀態(tài),可以是run芯丧,open旗国,stop(沒按樓層)狀態(tài)。如下:
Y:代表可以進行狀態(tài)轉(zhuǎn)化
N:代表不能進行轉(zhuǎn)化
O:代表自己對自己注整,忽略

open close run stop
open O Y N N
close Y O Y N
run N N O Y
stop Y N Y O

由于我們要進行電梯的狀態(tài)轉(zhuǎn)換能曾,因此需要定義出電梯的狀態(tài):

public interface ILift {
    public final static int OPEN_STATE = 1;
    public final static int CLOSE_STATE = 2;
    public final static int RUN_STATE = 3;
    public final static int STOP_STATE = 4;

    // 設(shè)置電梯狀態(tài)
    public void setState(int state);

    // 電梯門開狀態(tài)
    public void open();

    // 電梯關(guān)門狀態(tài)
    public void close();

    // 電梯移動狀態(tài)
    public void run();

    // 電梯停止?fàn)顟B(tài)
    public void stop();
}

在這邊我們把電梯看成了一個對象度硝,里面有狀態(tài)和狀態(tài)相應(yīng)的動作,可以想象后面我們的調(diào)用代碼基本就是依次調(diào)用Lift類的各個函數(shù)寿冕。

缺點:如果電梯還有其他狀態(tài)(比如通電蕊程,斷電狀態(tài)),則Lift類要修改驼唱,不符合開閉原則藻茂。

根據(jù)狀態(tài)模式,我們思考把狀態(tài)看做一個對象玫恳,更細粒度的切分電梯這個類辨赐,把電梯的每個狀態(tài)當(dāng)成一個類,我們來試驗下:

public abstract class LiftState {
    //狀態(tài)轉(zhuǎn)換
    private StageChange stageChange;
    // 電梯門開狀態(tài)
    public abstract void open();

    // 電梯關(guān)門狀態(tài)
    public abstract void close();

    // 電梯移動狀態(tài)
    public abstract void run();

    // 電梯停止?fàn)顟B(tài)
    public abstract void stop();
}

StageChange是狀態(tài)轉(zhuǎn)換類京办,用來進行狀態(tài)的裝換掀序。每個狀態(tài)都有自身的行為,比如Open狀態(tài)有一系列自己的行為:

public class LiftOpenState extends LiftState {
    public void open() {
        System.out.println("電梯門已經(jīng)開啟");
    }

    public void close() {
        super.stageChange.setLiftState(StageChange.closeState);
        super.stageChange.getLiftState().close();
        System.out.println("電梯關(guān)門");
    }

    public void run() {

    }

    public void stop() {

    }
}

狀態(tài)模式通過一系列狀態(tài)自身的流轉(zhuǎn)來達到不同的場景執(zhí)行不同的動作惭婿。

優(yōu)點

  • 結(jié)構(gòu)清晰
  • 封裝性好

狀態(tài)機

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末不恭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子财饥,更是在濱河造成了極大的恐慌换吧,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钥星,死亡現(xiàn)場離奇詭異沾瓦,居然都是意外死亡,警方通過查閱死者的電腦和手機谦炒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門暴拄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人编饺,你說我怎么就攤上這事乖篷。” “怎么了透且?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵撕蔼,是天一觀的道長。 經(jīng)常有香客問我秽誊,道長鲸沮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任锅论,我火速辦了婚禮讼溺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘最易。我一直安慰自己怒坯,他們只是感情好炫狱,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著剔猿,像睡著了一般视译。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上归敬,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天酷含,我揣著相機與錄音,去河邊找鬼汪茧。 笑死椅亚,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的舱污。 我是一名探鬼主播呀舔,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼慌闭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起躯舔,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驴剔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后粥庄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丧失,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年惜互,在試婚紗的時候發(fā)現(xiàn)自己被綠了布讹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡训堆,死狀恐怖描验,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坑鱼,我是刑警寧澤膘流,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站鲁沥,受9級特大地震影響呼股,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜画恰,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一彭谁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧允扇,春花似錦缠局、人聲如沸则奥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逞度。三九已至,卻和暖如春妙啃,著一層夾襖步出監(jiān)牢的瞬間档泽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工揖赴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留馆匿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓燥滑,卻偏偏與公主長得像渐北,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子铭拧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354

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

  • 初識 我第一次知道狀態(tài)機赃蛛,是在大學(xué)學(xué)習(xí)《數(shù)字電子技術(shù)基礎(chǔ)》的時候。一塊控制芯片有若干輸入數(shù)據(jù)總線Data_in搀菩,一...
    邱simple閱讀 25,765評論 2 15
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,101評論 1 32
  • javascript設(shè)計模式與開發(fā)實踐 設(shè)計模式 每個設(shè)計模式我們需要從三點問題入手: 定義 作用 用法與實現(xiàn) 單...
    穿牛仔褲的蚊子閱讀 4,058評論 0 13
  • 創(chuàng)建型模式 工廠模式 工廠模式(Factory Pattern)是 Java 中最常用的設(shè)計模式之一呕臂。這種類型的設(shè)...
    隔墻送來秋千影閱讀 2,669評論 0 11
  • “噠,噠肪跋,噠……”高跟鞋踏在地板的聲音在樓道間回響歧蒋,聲控?zé)粼谝凰查g亮起。她一邊爬著樓梯一邊想州既,丈夫現(xiàn)在是否...
    糖點什么閱讀 221評論 0 0