<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          設(shè)計(jì)模式詳解——狀態(tài)模式

          共 3237字,需瀏覽 7分鐘

           ·

          2021-10-25 01:14

          前言

          今天我們來(lái)看一個(gè)號(hào)稱策略模式雙胞胎的設(shè)計(jì)模式——狀態(tài)模式,如它的名字一樣,狀態(tài)模式最核心的設(shè)計(jì)思路就是將對(duì)象的狀態(tài)抽象出一個(gè)接口,然后根據(jù)它的不同狀態(tài)封裝其行為,這樣就可以實(shí)現(xiàn)狀態(tài)和行為的綁定,最終實(shí)現(xiàn)對(duì)象和狀態(tài)的有效解耦。下面我們就來(lái)詳細(xì)看下它的基本原理和實(shí)現(xiàn)過(guò)程吧。

          狀態(tài)模式

          狀態(tài)模式允許對(duì)象在內(nèi)部狀態(tài)改變時(shí)改變它的行為,對(duì)象看起來(lái)好像修改了它的類。

          要點(diǎn)

          • 狀態(tài)模式允許一個(gè)對(duì)象基于內(nèi)部狀態(tài)而擁有不同的行為
          • 和程序狀態(tài)機(jī)(PSM)不同,狀態(tài)模式用類代表狀態(tài)
          • Context會(huì)將行為委托給當(dāng)前狀態(tài)對(duì)象
          • 通過(guò)將每個(gè)狀態(tài)封裝進(jìn)一個(gè)類,我們把以后需要做的任何改變局部化了
          • 狀態(tài)模式和策略模式有相同的類圖,但是它們的意圖不同
          • 策略模式通常會(huì)用行為或算法來(lái)配置Context
          • 狀態(tài)模式允許Context隨著狀態(tài)的改變而改變行為
          • 狀態(tài)轉(zhuǎn)換可以由State類或Context類控制
          • 使用狀態(tài)模式通常會(huì)導(dǎo)致設(shè)計(jì)中類的數(shù)目大量增加
          • 狀態(tài)類可以被多個(gè)Context示例共享

          優(yōu)缺點(diǎn)

          優(yōu)點(diǎn)
          1. 封裝了轉(zhuǎn)換規(guī)則。

          2. 枚舉可能的狀態(tài),在枚舉狀態(tài)之前需要確定狀態(tài)種類。

          3. 將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類中,并且可以方便地增加新的狀態(tài),只需要改變對(duì)象狀態(tài)即可改變對(duì)象的行為。

          4. 允許狀態(tài)轉(zhuǎn)換邏輯與狀態(tài)對(duì)象合成一體,而不是某一個(gè)巨大的條件語(yǔ)句塊

          5. 可以讓多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù)。

          缺點(diǎn)
          1. 狀態(tài)模式的使用必然會(huì)增加系統(tǒng)類和對(duì)象的個(gè)數(shù)。
          2. 狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂。
          3. 狀態(tài)模式對(duì)"開閉原則"的支持并不太好,對(duì)于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源代碼,否則無(wú)法切換到新增狀態(tài),而且修改某個(gè)狀態(tài)類的行為也需修改對(duì)應(yīng)類的源代碼。

          使用場(chǎng)景

          1. 行為隨狀態(tài)改變而改變的場(chǎng)景。
          2. 條件、分支語(yǔ)句的代替者。

          示例

          狀態(tài)接口

          首先是狀態(tài)接口,這個(gè)接口是給我們實(shí)際的狀態(tài)對(duì)象繼承的,這個(gè)接口有一個(gè)方法doAction,這個(gè)方法就是給不同的狀態(tài)對(duì)象實(shí)現(xiàn)的,用于處理不同狀態(tài)下的行為的。

          public?interface?State?{
          ????/**
          ?????*?改變狀態(tài)的操作
          ?????*?@param?context
          ?????*/

          ????void?doAction(Context?context);
          }
          狀態(tài)所屬者

          然后是我們的狀態(tài)所屬者,這個(gè)類有一個(gè)核心的屬性就是我們的State接口。

          public?class?Context?{
          ????private?State?state;

          ????public?Context(){}

          ????public?void?setState(State?state){
          ????????this.state?=?state;
          ????}

          ????public?State?getState(){
          ????????return?state;
          ????}
          ?????@Override
          ????public?String?toString()?{
          ????????return?"Context{"?+
          ????????????????"state="?+?state?+
          ????????????????'}';
          ????}
          }
          狀態(tài)實(shí)現(xiàn)

          狀態(tài)實(shí)現(xiàn)者繼承了State接口,并實(shí)現(xiàn)了doAction方法,在方法內(nèi)部可以對(duì)我們的狀態(tài)所有者進(jìn)行對(duì)應(yīng)的操作。

          這里是一個(gè)啟動(dòng)狀態(tài):

          public?class?StopState?implements?State?{

          ????private?String?name;

          ????public?StopState()?{
          ????????this.name?=?"stop";
          ????}

          ????@Override
          ????public?void?doAction(Context?context)?{
          ????????System.out.println("Context?is?in?stop?state");
          ????????context.setState(this);
          ????????System.out.println(context);
          ????}

          ????@Override
          ????public?String?toString()?{
          ????????return?"StopState{"?+
          ????????????????"name='"?+?name?+?'\''?+
          ????????????????'}';
          ????}
          }

          這里是停止?fàn)顟B(tài)

          public?class?StartState?implements?State{

          ????private?String?name;

          ????public?StartState()?{
          ????????this.name?=?"start";
          ????}

          ????@Override
          ????public?void?doAction(Context?context)?{
          ????????System.out.println("Context?is?in?start?state");
          ????????context.setState(this);
          ????????System.out.println(context);
          ????}

          ????@Override
          ????public?String?toString()?{
          ????????return?"StartState{"?+
          ????????????????"name='"?+?name?+?'\''?+
          ????????????????'}';
          ????}
          }
          測(cè)試代碼

          這里分別實(shí)例化了容器和狀態(tài)的示例,然后通過(guò)示例的doAction方法操作容器

          @Test
          ????public?void?testState()?{
          ????????Context?context?=?new?Context();

          ????????StartState?startState?=?new?StartState();
          ????????startState.doAction(context);


          ????????StopState?stopState?=?new?StopState();
          ????????stopState.doAction(context);

          ????}
          運(yùn)行結(jié)果

          可以看到,狀態(tài)對(duì)象的doAction方法執(zhí)行后,容器對(duì)應(yīng)的狀態(tài)也發(fā)生了改變:

          好了,關(guān)于狀態(tài)模式就先說(shuō)這么多,接下來(lái)我們做一個(gè)簡(jiǎn)單的總結(jié)。

          總結(jié)

          有用過(guò)策略模式或者對(duì)策略模式比較熟悉的小伙伴應(yīng)該發(fā)現(xiàn)了:策略模式其實(shí)和我們今天分析狀態(tài)模式特別像,甚至連架構(gòu)模式都是一樣的,所以這里我們有必要說(shuō)下它們的區(qū)別。

          首先是策略模式,它其實(shí)是將不同的算法封裝成不同的策略,然后在具體的策略中實(shí)現(xiàn)具體的行為,但是測(cè)試本身是被動(dòng)被選擇的,容器選擇策略,調(diào)用過(guò)程發(fā)生在容器中,而且策略本身是入?yún)ⅲ?/p>

          而我們今天分析的狀態(tài)模式,它是將不同狀態(tài)對(duì)應(yīng)的行為封裝,然后由具體的狀態(tài)操作容器,整個(gè)過(guò)程更像是狀態(tài)主動(dòng)發(fā)起的,由狀態(tài)執(zhí)行其自己的方法,入?yún)⑹侨萜鳌?/p>

          這兩種設(shè)計(jì)模式從某種程度上說(shuō)是可以互相替換的,但是還是要結(jié)合具體業(yè)務(wù)分析的,比如spring boot啟動(dòng)過(guò)程中,它用到的就是狀態(tài)模式,這一點(diǎn)我們?cè)诜治?code style="overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;background-color: rgba(27, 31, 35, 0.05);font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;color: rgb(255, 100, 65);">spring boot啟動(dòng)過(guò)程中也發(fā)現(xiàn)了;但如果是涉及到算法層面的內(nèi)容,比如兩個(gè)數(shù)的加減乘除,顯然策略模式才是更好的選擇。

          總之,學(xué)習(xí)設(shè)計(jì)模式除了要了解它的基本原理和應(yīng)用場(chǎng)景之外,更重要的是,要學(xué)會(huì)辨識(shí)優(yōu)秀框架中的設(shè)計(jì)模式(知識(shí),知就是知道,了解,識(shí)就是辨識(shí),分析),最終將這些設(shè)計(jì)模式應(yīng)用到我們的業(yè)務(wù)開發(fā)之中。

          - END -


          瀏覽 47
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩人妻不卡 | 18禁成人黄官网 | 好屌日在线视频 | 精品内射无码 | 在线观看免费成人网站 |