34 設計模式——狀態(tài)模式 詳解

在軟件開發(fā)過程中伤柄,應用程序中的部分對象可能會根據(jù)不同的情況做出不同的行為绊困,我們把這種對象稱為有狀態(tài)的對象,而把影響對象行為的一個或多個動態(tài)變化的屬性稱為狀態(tài)适刀。當有狀態(tài)的對象與外部事件產(chǎn)生互動時秤朗,其內部狀態(tài)就會發(fā)生改變,從而使其行為也發(fā)生改變笔喉。如人都有高興和傷心的時候取视,不同的情緒有不同的行為,當然外界也會影響其情緒變化常挚。

對這種有狀態(tài)的對象編程作谭,傳統(tǒng)的解決方案是:將這些所有可能發(fā)生的情況全都考慮到,然后使用 if-else 或 switch-case 語句來做狀態(tài)判斷奄毡,再進行不同情況的處理折欠。但是顯然這種做法對復雜的狀態(tài)判斷存在天然弊端,條件判斷語句會過于臃腫吼过,可讀性差锐秦,且不具備擴展性,維護難度也大那先。且增加新的狀態(tài)時要添加新的 if-else 語句农猬,這違背了“開閉原則”,不利于程序的擴展售淡。

以上問題如果采用“狀態(tài)模式”就能很好地得到解決斤葱。狀態(tài)模式的解決思想是:當控制一個對象狀態(tài)轉換的條件表達式過于復雜時,把相關“判斷邏輯”提取出來揖闸,用各個不同的類進行表示揍堕,系統(tǒng)處于哪種情況,直接使用相應的狀態(tài)類對象進行處理汤纸,這樣能把原來復雜的邏輯判斷簡單化衩茸,消除了 if-else、switch-case 等冗余語句贮泞,代碼更有層次性楞慈,并且具備良好的擴展力幔烛。

狀態(tài)模式的定義與特點

狀態(tài)(State)模式的定義:對有狀態(tài)的對象,把復雜的“判斷邏輯”提取到不同的狀態(tài)對象中囊蓝,允許狀態(tài)對象在其內部狀態(tài)發(fā)生改變時改變其行為饿悬。

狀態(tài)模式是一種對象行為型模式,其主要優(yōu)點如下聚霜。

  1. 結構清晰狡恬,狀態(tài)模式將與特定狀態(tài)相關的行為局部化到一個狀態(tài)中,并且將不同狀態(tài)的行為分割開來蝎宇,滿足“單一職責原則”弟劲。
  2. 將狀態(tài)轉換顯示化,減少對象間的相互依賴姥芥。將不同的狀態(tài)引入獨立的對象中會使得狀態(tài)轉換變得更加明確兔乞,且減少對象間的相互依賴。
  3. 狀態(tài)類職責明確撇眯,有利于程序的擴展报嵌。通過定義新的子類很容易地增加新的狀態(tài)和轉換。

狀態(tài)模式的主要缺點如下熊榛。

  1. 狀態(tài)模式的使用必然會增加系統(tǒng)的類與對象的個數(shù)锚国。
  2. 狀態(tài)模式的結構與實現(xiàn)都較為復雜,如果使用不當會導致程序結構和代碼的混亂玄坦。
  3. 狀態(tài)模式對開閉原則的支持并不太好血筑,對于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類需要修改那些負責狀態(tài)轉換的源碼煎楣,否則無法切換到新增狀態(tài)豺总,而且修改某個狀態(tài)類的行為也需要修改對應類的源碼。

狀態(tài)模式的結構與實現(xiàn)

狀態(tài)模式把受環(huán)境改變的對象行為包裝在不同的狀態(tài)對象里择懂,其意圖是讓一個對象在其內部狀態(tài)改變的時候喻喳,其行為也隨之改變。現(xiàn)在我們來分析其基本結構和實現(xiàn)方法困曙。

1. 模式的結構

狀態(tài)模式包含以下主要角色表伦。

  1. 環(huán)境類(Context)角色:也稱為上下文,它定義了客戶端需要的接口慷丽,內部維護一個當前狀態(tài)蹦哼,并負責具體狀態(tài)的切換。
  2. 抽象狀態(tài)(State)角色:定義一個接口要糊,用以封裝環(huán)境對象中的特定狀態(tài)所對應的行為纲熏,可以有一個或多個行為。
  3. 具體狀態(tài)(Concrete State)角色:實現(xiàn)抽象狀態(tài)所對應的行為,并且在需要的情況下進行狀態(tài)切換局劲。

其結構圖如圖 1 所示勺拣。

3-1Q11615412U55.gif

圖1 狀態(tài)模式的結構圖

2. 模式的實現(xiàn)

狀態(tài)模式的實現(xiàn)代碼如下:

public class StatePatternClient {
    public static void main(String[] args) {
        Context context = new Context();    //創(chuàng)建環(huán)境      
        context.Handle();    //處理請求
        context.Handle();
        context.Handle();
        context.Handle();
    }
}
//環(huán)境類
class Context {
    private State state;
    //定義環(huán)境類的初始狀態(tài)
    public Context() {
        this.state = new ConcreteStateA();
    }
    //設置新狀態(tài)
    public void setState(State state) {
        this.state = state;
    }
    //讀取狀態(tài)
    public State getState() {
        return (state);
    }
    //對請求做處理
    public void Handle() {
        state.Handle(this);
    }
}
//抽象狀態(tài)類
abstract class State {
    public abstract void Handle(Context context);
}
//具體狀態(tài)A類
class ConcreteStateA extends State {
    public void Handle(Context context) {
        System.out.println("當前狀態(tài)是 A.");
        context.setState(new ConcreteStateB());
    }
}
//具體狀態(tài)B類
class ConcreteStateB extends State {
    public void Handle(Context context) {
        System.out.println("當前狀態(tài)是 B.");
        context.setState(new ConcreteStateA());
    }
}

程序運行結果如下:

當前狀態(tài)是 A.
當前狀態(tài)是 B.
當前狀態(tài)是 A.
當前狀態(tài)是 B.

狀態(tài)模式的應用實例

【例1】用“狀態(tài)模式”設計一個學生成績的狀態(tài)轉換程序。

分析:本實例包含了“不及格”“中等”和“優(yōu)秀” 3 種狀態(tài)容握,當學生的分數(shù)小于 60 分時為“不及格”狀態(tài)宣脉,當分數(shù)大于等于 60 分且小于 90 分時為“中等”狀態(tài),當分數(shù)大于等于 90 分時為“優(yōu)秀”狀態(tài)剔氏,我們用狀態(tài)模式來實現(xiàn)這個程序。

首先竹祷,定義一個抽象狀態(tài)類(AbstractState)谈跛,其中包含了環(huán)境屬性、狀態(tài)名屬性和當前分數(shù)屬性塑陵,以及加減分方法 addScore(intx) 和檢查當前狀態(tài)的抽象方法 checkState()感憾。

然后,定義“不及格”狀態(tài)類 LowState令花、“中等”狀態(tài)類 MiddleState 和“優(yōu)秀”狀態(tài)類 HighState阻桅,它們是具體狀態(tài)類,實現(xiàn) checkState() 方法兼都,負責檢査自己的狀態(tài)嫂沉,并根據(jù)情況轉換。

最后扮碧,定義環(huán)境類(ScoreContext)趟章,其中包含了當前狀態(tài)對象和加減分的方法 add(int score),客戶類通過該方法來改變成績狀態(tài)慎王。圖 2 所示是其結構圖蚓土。

3-1Q11615425V39.gif

圖2 學生成績的狀態(tài)轉換程序的結構圖

程序代碼如下:

public class ScoreStateTest {
    public static void main(String[] args) {
        ScoreContext account = new ScoreContext();
        System.out.println("學生成績狀態(tài)測試:");
        account.add(30);
        account.add(40);
        account.add(25);
        account.add(-15);
        account.add(-25);
    }
}
//環(huán)境類
class ScoreContext {
    private AbstractState state;
    ScoreContext() {
        state = new LowState(this);
    }
    public void setState(AbstractState state) {
        this.state = state;
    }
    public AbstractState getState() {
        return state;
    }
    public void add(int score) {
        state.addScore(score);
    }
}
//抽象狀態(tài)類
abstract class AbstractState {
    protected ScoreContext hj;  //環(huán)境
    protected String stateName; //狀態(tài)名
    protected int score; //分數(shù)
    public abstract void checkState(); //檢查當前狀態(tài)
    public void addScore(int x) {
        score += x;
        System.out.print("加上:" + x + "分,\t當前分數(shù):" + score);
        checkState();
        System.out.println("分赖淤,\t當前狀態(tài):" + hj.getState().stateName);
    }
}
//具體狀態(tài)類:不及格
class LowState extends AbstractState {
    public LowState(ScoreContext h) {
        hj = h;
        stateName = "不及格";
        score = 0;
    }
    public LowState(AbstractState state) {
        hj = state.hj;
        stateName = "不及格";
        score = state.score;
    }
    public void checkState() {
        if (score >= 90) {
            hj.setState(new HighState(this));
        } else if (score >= 60) {
            hj.setState(new MiddleState(this));
        }
    }
}
//具體狀態(tài)類:中等
class MiddleState extends AbstractState {
    public MiddleState(AbstractState state) {
        hj = state.hj;
        stateName = "中等";
        score = state.score;
    }
    public void checkState() {
        if (score < 60) {
            hj.setState(new LowState(this));
        } else if (score >= 90) {
            hj.setState(new HighState(this));
        }
    }
}
//具體狀態(tài)類:優(yōu)秀
class HighState extends AbstractState {
    public HighState(AbstractState state) {
        hj = state.hj;
        stateName = "優(yōu)秀";
        score = state.score;
    }
    public void checkState() {
        if (score < 60) {
            hj.setState(new LowState(this));
        } else if (score < 90) {
            hj.setState(new MiddleState(this));
        }
    }
}

程序運行結果如下:

學生成績狀態(tài)測試:
加上:30分蜀漆,    當前分數(shù):30分,    當前狀態(tài):不及格
加上:40分咱旱,    當前分數(shù):70分确丢,    當前狀態(tài):中等
加上:25分,    當前分數(shù):95分莽龟,    當前狀態(tài):優(yōu)秀
加上:-15分蠕嫁,    當前分數(shù):80分,    當前狀態(tài):中等
加上:-25分毯盈,    當前分數(shù):55分剃毒,    當前狀態(tài):不及格

【例2】用“狀態(tài)模式”設計一個多線程的狀態(tài)轉換程序。

分析:多線程存在 5 種狀態(tài),分別為新建狀態(tài)赘阀、就緒狀態(tài)益缠、運行狀態(tài)、阻塞狀態(tài)和死亡狀態(tài)基公,各個狀態(tài)當遇到相關方法調用或事件觸發(fā)時會轉換到其他狀態(tài)幅慌,其狀態(tài)轉換規(guī)律如圖 3 所示。

3-1Q116154332451.gif

圖3 線程狀態(tài)轉換圖

現(xiàn)在先定義一個抽象狀態(tài)類(TheadState)轰豆,然后為圖 3 所示的每個狀態(tài)設計一個具體狀態(tài)類胰伍,它們是新建狀態(tài)(New)、就緒狀態(tài)(Runnable )酸休、運行狀態(tài)(Running)骂租、阻塞狀態(tài)(Blocked)和死亡狀態(tài)(Dead),每個狀態(tài)中有觸發(fā)它們轉變狀態(tài)的方法斑司,環(huán)境類(ThreadContext)中先生成一個初始狀態(tài)(New)渗饮,并提供相關觸發(fā)方法,圖 4 所示是線程狀態(tài)轉換程序的結構圖宿刮。

3-1Q116154432352.gif

圖4 線程狀態(tài)轉換程序的結構圖

程序代碼如下:

public class ScoreStateTest {
    public static void main(String[] args) {
        ThreadContext context = new ThreadContext();
        context.start();
        context.getCPU();
        context.suspend();
        context.resume();
        context.getCPU();
        context.stop();
    }
}
//環(huán)境類
class ThreadContext {
    private ThreadState state;
    ThreadContext() {
        state = new New();
    }
    public void setState(ThreadState state) {
        this.state = state;
    }
    public ThreadState getState() {
        return state;
    }
    public void start() {
        ((New) state).start(this);
    }
    public void getCPU() {
        ((Runnable) state).getCPU(this);
    }
    public void suspend() {
        ((Running) state).suspend(this);
    }
    public void stop() {
        ((Running) state).stop(this);
    }
    public void resume() {
        ((Blocked) state).resume(this);
    }
}
//抽象狀態(tài)類:線程狀態(tài)
abstract class ThreadState {
    protected String stateName; //狀態(tài)名
}
//具體狀態(tài)類:新建狀態(tài)
class New extends ThreadState {
    public New() {
        stateName = "新建狀態(tài)";
        System.out.println("當前線程處于:新建狀態(tài).");
    }
    public void start(ThreadContext hj) {
        System.out.print("調用start()方法-->");
        if (stateName.equals("新建狀態(tài)")) {
            hj.setState(new Runnable());
        } else {
            System.out.println("當前線程不是新建狀態(tài)互站,不能調用start()方法.");
        }
    }
}
//具體狀態(tài)類:就緒狀態(tài)
class Runnable extends ThreadState {
    public Runnable() {
        stateName = "就緒狀態(tài)";
        System.out.println("當前線程處于:就緒狀態(tài).");
    }
    public void getCPU(ThreadContext hj) {
        System.out.print("獲得CPU時間-->");
        if (stateName.equals("就緒狀態(tài)")) {
            hj.setState(new Running());
        } else {
            System.out.println("當前線程不是就緒狀態(tài),不能獲取CPU.");
        }
    }
}
//具體狀態(tài)類:運行狀態(tài)
class Running extends ThreadState {
    public Running() {
        stateName = "運行狀態(tài)";
        System.out.println("當前線程處于:運行狀態(tài).");
    }
    public void suspend(ThreadContext hj) {
        System.out.print("調用suspend()方法-->");
        if (stateName.equals("運行狀態(tài)")) {
            hj.setState(new Blocked());
        } else {
            System.out.println("當前線程不是運行狀態(tài)僵缺,不能調用suspend()方法.");
        }
    }
    public void stop(ThreadContext hj) {
        System.out.print("調用stop()方法-->");
        if (stateName.equals("運行狀態(tài)")) {
            hj.setState(new Dead());
        } else {
            System.out.println("當前線程不是運行狀態(tài)胡桃,不能調用stop()方法.");
        }
    }
}
//具體狀態(tài)類:阻塞狀態(tài)
class Blocked extends ThreadState {
    public Blocked() {
        stateName = "阻塞狀態(tài)";
        System.out.println("當前線程處于:阻塞狀態(tài).");
    }
    public void resume(ThreadContext hj) {
        System.out.print("調用resume()方法-->");
        if (stateName.equals("阻塞狀態(tài)")) {
            hj.setState(new Runnable());
        } else {
            System.out.println("當前線程不是阻塞狀態(tài),不能調用resume()方法.");
        }
    }
}
//具體狀態(tài)類:死亡狀態(tài)
class Dead extends ThreadState {
    public Dead() {
        stateName = "死亡狀態(tài)";
        System.out.println("當前線程處于:死亡狀態(tài).");
    }
}

程序運行結果如下:

當前線程處于:新建狀態(tài).
調用start()方法-->當前線程處于:就緒狀態(tài).
獲得CPU時間-->當前線程處于:運行狀態(tài).
調用suspend()方法-->當前線程處于:阻塞狀態(tài).
調用resume()方法-->當前線程處于:就緒狀態(tài).
獲得CPU時間-->當前線程處于:運行狀態(tài).
調用stop()方法-->當前線程處于:死亡狀態(tài).

狀態(tài)模式的應用場景

通常在以下情況下可以考慮使用狀態(tài)模式谤饭。

  • 當一個對象的行為取決于它的狀態(tài)标捺,并且它必須在運行時根據(jù)狀態(tài)改變它的行為時,就可以考慮使用狀態(tài)模式揉抵。
  • 一個操作中含有龐大的分支結構亡容,并且這些分支決定于對象的狀態(tài)時。

狀態(tài)模式的擴展

在有些情況下冤今,可能有多個環(huán)境對象需要共享一組狀態(tài)闺兢,這時需要引入享元模式,將這些具體狀態(tài)對象放在集合中供程序共享戏罢,其結構圖如圖 5 所示屋谭。

3-1Q116154539147.gif

圖5 共享狀態(tài)模式的結構圖

分析:共享狀態(tài)模式的不同之處是在環(huán)境類中增加了一個 HashMap 來保存相關狀態(tài),當需要某種狀態(tài)時可以從中獲取龟糕,其程序代碼如下:

package state;
import java.util.HashMap;
public class FlyweightStatePattern {
    public static void main(String[] args) {
        ShareContext context = new ShareContext(); //創(chuàng)建環(huán)境      
        context.Handle(); //處理請求
        context.Handle();
        context.Handle();
        context.Handle();
    }
}
//環(huán)境類
class ShareContext {
    private ShareState state;
    private HashMap<String, ShareState> stateSet = new HashMap<String, ShareState>();
    public ShareContext() {
        state = new ConcreteState1();
        stateSet.put("1", state);
        state = new ConcreteState2();
        stateSet.put("2", state);
        state = getState("1");
    }
    //設置新狀態(tài)
    public void setState(ShareState state) {
        this.state = state;
    }
    //讀取狀態(tài)
    public ShareState getState(String key) {
        ShareState s = (ShareState) stateSet.get(key);
        return s;
    }
    //對請求做處理
    public void Handle() {
        state.Handle(this);
    }
}
//抽象狀態(tài)類
abstract class ShareState {
    public abstract void Handle(ShareContext context);
}
//具體狀態(tài)1類
class ConcreteState1 extends ShareState {
    public void Handle(ShareContext context) {
        System.out.println("當前狀態(tài)是: 狀態(tài)1");
        context.setState(context.getState("2"));
    }
}
//具體狀態(tài)2類
class ConcreteState2 extends ShareState {
    public void Handle(ShareContext context) {
        System.out.println("當前狀態(tài)是: 狀態(tài)2");
        context.setState(context.getState("1"));
    }
}

程序運行結果如下:

當前狀態(tài)是: 狀態(tài)1
當前狀態(tài)是: 狀態(tài)2
當前狀態(tài)是: 狀態(tài)1
當前狀態(tài)是: 狀態(tài)2

拓展

狀態(tài)模式與責任鏈模式的區(qū)別

狀態(tài)模式和責任鏈模式都能消除 if-else 分支過多的問題桐磁。但在某些情況下,狀態(tài)模式中的狀態(tài)可以理解為責任讲岁,那么在這種情況下我擂,兩種模式都可以使用衬以。

從定義來看,狀態(tài)模式強調的是一個對象內在狀態(tài)的改變校摩,而責任鏈模式強調的是外部節(jié)點對象間的改變看峻。

從代碼實現(xiàn)上來看,兩者最大的區(qū)別就是狀態(tài)模式的各個狀態(tài)對象知道自己要進入的下一個狀態(tài)對象衙吩,而責任鏈模式并不清楚其下一個節(jié)點處理對象互妓,因為鏈式組裝由客戶端負責。

狀態(tài)模式與策略模式的區(qū)別

狀態(tài)模式和策略模式的 UML 類圖架構幾乎完全一樣坤塞,但兩者的應用場景是不一樣的冯勉。策略模式的多種算法行為擇其一都能滿足,彼此之間是獨立的尺锚,用戶可自行更換策略算法珠闰,而狀態(tài)模式的各個狀態(tài)間存在相互關系,彼此之間在一定條件下存在自動切換狀態(tài)的效果瘫辩,并且用戶無法指定狀態(tài),只能設置初始狀態(tài)坛悉。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末伐厌,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子裸影,更是在濱河造成了極大的恐慌挣轨,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轩猩,死亡現(xiàn)場離奇詭異卷扮,居然都是意外死亡,警方通過查閱死者的電腦和手機均践,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門晤锹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人彤委,你說我怎么就攤上這事鞭铆。” “怎么了焦影?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵车遂,是天一觀的道長。 經(jīng)常有香客問我斯辰,道長舶担,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任彬呻,我火速辦了婚禮衣陶,結果婚禮上柄瑰,老公的妹妹穿的比我還像新娘。我一直安慰自己祖搓,他們只是感情好狱意,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拯欧,像睡著了一般详囤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上镐作,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天藏姐,我揣著相機與錄音,去河邊找鬼该贾。 笑死羔杨,一個胖子當著我的面吹牛,可吹牛的內容都是我干的杨蛋。 我是一名探鬼主播兜材,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼逞力!你這毒婦竟也來了曙寡?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤寇荧,失蹤者是張志新(化名)和其女友劉穎举庶,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體揩抡,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡户侥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了峦嗤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蕊唐。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖寻仗,靈堂內的尸體忽然破棺而出刃泌,到底是詐尸還是另有隱情,我是刑警寧澤署尤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布耙替,位于F島的核電站,受9級特大地震影響曹体,放射性物質發(fā)生泄漏俗扇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一箕别、第九天 我趴在偏房一處隱蔽的房頂上張望铜幽。 院中可真熱鬧滞谢,春花似錦、人聲如沸除抛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽到忽。三九已至橄教,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工料饥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人遭垛。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子堤魁,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內容

  • 在軟件開發(fā)過程中,應用程序中的有些對象可能會根據(jù)不同的情況做出不同的行為返十,我們把這種對象稱為有狀態(tài)的對象姨涡,而把影響...
    Zal哥哥閱讀 638評論 0 0
  • 點贊再看,養(yǎng)成習慣吧慢,公眾號搜一搜【一角錢技術[https://p3-juejin.byteimg.com/tos-...
    一角錢技術閱讀 504評論 2 9
  • 在軟件開發(fā)過程中,應用程序中的有些對象可能會根據(jù)不同的情況做出不同的行為赏表,我們把這種對象稱為有狀態(tài)的對象检诗,而把影響...
    兜兜_2925閱讀 296評論 0 1
  • 狀態(tài)模式(State) 在軟件開發(fā)過程中,應用程序中的有些對象可能會根據(jù)不同的情況做出不同的行為瓢剿,我們把這種對象稱...
    Acton_zhang閱讀 244評論 0 1
  • 在軟件開發(fā)過程中逢慌,應用程序中的有些對象可能會根據(jù)不同的情況做出不同的行為,我們把這種對象稱為有狀態(tài)的對象间狂,而把影響...
    迷心迷閱讀 269評論 0 1