概要
本來不准備寫Status模式,因為它跟Strategy模式簡直就是對孿生兄弟,類結構類似,處理方式類似,相像的幾乎沒有多少好說的,後來權衡了下,畢竟這也是GOF單獨提出來的一種模式,而且Status模式跟Stragegy模式的關注點多少還是有些不同的。那麼Status模式到底能做什麼,怎麼做的呢?
程序中經常會涉及到各種狀態,每種狀態下會有不同的處理邏輯,狀態之間能進行切換,切換狀態的同時也需要改變它們的行為,這種情況下我們的程序很容易陷入各種耦合的泥潭,Status模式可以幫助我們解決這類問題,使程序易於擴展,調理清晰。其實Strategy模式封裝的是算法間的切換,而Status模式做的則是狀態間的切換,關注點不同,但思路則是一樣的。Strategy模式可以參考下文:
【設計模式系列】行為型模式之Strategy模式
目的
把各種狀態獨立封裝,而把狀態切換及相應處理隔離出來,使對象在改變內部狀態時也改變對應狀態的行為。
實例
開發一個項目管理系統,項目會經歷各個階段(可以看做各個狀態),這裡假設只考慮4個階段:需求,設計,編碼,測試。處於不同階段時,系統可以輸出不同的項目文檔報告,比如需求階段輸出需求文檔,設計時為設計文檔,編碼時為代碼評審記錄,測試時則是測試文檔。看看基於Status模式會怎麼考慮。
我們把各種階段(狀態)封裝到不同的類,每個狀態類都會有Report方法來處理不同的報告內容,而這些狀態類不會去關心狀態怎麼切換,行為怎麼改變,這些處理會封裝到獨立的Context類,類圖和代碼如下:
[cpp]
class Status {
public:
virtual void Report() = 0;
};
class RequirementSts : public Status {
public:
virtual void Report() {};
};
class DesignSts : public Status {
public:
virtual void Report() {};
};
class CodingSts : public Status {
public:
virtual void Report() {};
};
class TestingSts : public Status {
public:
virtual void Report() {};
};
class Context {
public:
Context(Status* sts) {
mSts = sts;
}
void SetStatus(Status* sts) {
mSts = sts;
}
void Report() {
mSts->Report();
}
private:
Status* mSts;
};
Client可以這樣去使用:
[cpp]
Status* require = new RequirementSts();
Context* cntxt = new Context(require);
cntxt ->Report(); // requirement report
Status* design = new DesignSts();
Context* cntxt = new Context(design);
cntxt ->Report(); // design report
......
可以看出當Context類的狀態發生變化時,對應的行為也會自動變化。當然我們還能更進一步,可以把狀態變化的流程也封裝到Context類中,首先Context類需要包含四種狀態的對象,也就是在構造函數參數中需要傳遞一個狀態組,然後把狀態切換的流程封裝到NextStatus方法,Client可以通過調用NextStatus方法自動切換狀態和行為,代碼如下:
[cpp]
class Context {
public:
Context(Status** sts, int stsCount) {
mSts = sts;
mCount = stsCount;
mIndex = 0;
}
void NextStatus() {
mIndex++;
if (mIndex >= mCount) {
mIndex = 0;
}
}
void Report() {
mSts[mIndex]->Report();
}
private:
Status** mSts;
int mCount;
int mIndex;
};
Client的調用:
[cpp]
Status* sts[4];
sts[0] = new RequirementSts();
sts[1] = new DesignSts();
sts[2] = new CodingSts();
sts[3] = new TestingSts();
Context* cntxt = new Context(sts);
cntxt ->Report(); // requirement report
cntxt->NextStatus();
cntxt ->Report(); // design report
cntxt->NextStatus();
cntxt ->Report(); // coding report
cntxt->NextStatus();
cntxt ->Report(); // testing report
作者:my_business