| 源代碼下載  嚴(yán)風(fēng)吹霜海草凋,筋干精堅(jiān)胡馬驕。 漢家戰(zhàn)士三十萬(wàn),將軍兼領(lǐng)霍嫖姚。 流星白羽腰間插,劍花秋蓮光出匣。 天兵照雪下玉關(guān),虜箭如沙射金甲。 云龍風(fēng)虎盡交回,太白入月敵可摧。 敵可摧,旄頭滅,履胡之腸涉胡血。 懸胡青天上,埋胡紫塞旁。 胡無(wú)人,漢道昌。   李白這首詩(shī)豪氣萬(wàn)丈的詩(shī)篇,描述的是漢驃騎將軍霍去病率領(lǐng)大軍,出隴西,突襲匈奴部落的戰(zhàn)爭(zhēng)場(chǎng)面,千載之下,猶讓人感覺(jué)豪邁異常。匈奴和漢朝的爭(zhēng)端從漢高祖劉邦開(kāi)始。楚漢之爭(zhēng)過(guò)后,劉邦統(tǒng)一了中國(guó)。此時(shí),匈奴部族也被冒頓(這兩字發(fā)音應(yīng)為mo du)單于統(tǒng)一了起來(lái)。匈奴逐漸強(qiáng)大的同時(shí),開(kāi)始窺覷漢朝的疆土。冒頓單于領(lǐng)軍進(jìn)犯太原,包圍晉陽(yáng)。劉邦親率30萬(wàn)大軍進(jìn)擊匈奴,不期竟中匈奴之計(jì),被困于白登。幸虧用陳平之計(jì),送重禮于冒頓夫人,走枕邊風(fēng)路線,才讓匈奴大軍讓開(kāi)一條路,逃了出來(lái),狼狽之極。這場(chǎng)戰(zhàn)役的結(jié)果就是漢朝采取和親政策,送漢宗室之女給匈奴王為妾,并借機(jī)進(jìn)貢。但這也避免不了匈奴侵犯漢族邊界,殺戮漢民,搶奪牲畜。這樣的歷史持續(xù)了數(shù)十年,直到漢武帝的時(shí)候還保持著。而雄才大略的武帝,豈能容忍此奇恥大辱。堅(jiān)毅勇猛的他,籌劃著對(duì)匈奴的打擊,經(jīng)過(guò)一系列的改革(個(gè)人覺(jué)得他改革兵種,將以車(chē)兵步兵為主的軍隊(duì)改為輕騎兵為主,對(duì)這場(chǎng)戰(zhàn)役意義最為重大),開(kāi)始了對(duì)匈奴的窮追猛打。這段歷史造就了中國(guó)歷史上兩顆耀眼的將星:衛(wèi)青,霍去病?;羧ゲ「訆Z目,他18歲的時(shí)候,隨衛(wèi)青大軍出征。他率領(lǐng)800輕騎,遠(yuǎn)離大軍,奔赴敵人腹地,斬?cái)扯в嗳?。被漢武帝封為冠軍侯。后又率1萬(wàn)大軍出隴西,轉(zhuǎn)戰(zhàn)千余里,斬獲8000于人。再于同年秋天,出北地,攻祁連山,大獲全勝,斬獲三萬(wàn)余人。漢朝與匈奴的最后一次大型戰(zhàn)役也由衛(wèi)青,霍去病完成?;羧ゲ∮H率5萬(wàn)騎兵遠(yuǎn)離代郡,對(duì)匈奴人窮追猛打,殲敵七萬(wàn)余人。乘勝追擊到狼居胥山(今在蒙古境內(nèi)),并在此舉行祭天儀式(封狼居胥)。此時(shí)的霍去病僅僅21歲,但二年后英年早逝。在他短暫的一生中四次與匈奴做戰(zhàn),轉(zhuǎn)戰(zhàn)數(shù)千余里,滅敵十余萬(wàn)人,徹底熄滅了匈奴人的囂張氣焰,也給大漢的邊境帶來(lái)了安寧。不僅如此,他還留下了“匈奴未滅,何以家為”的千古豪言。真是錚錚男兒形象,為萬(wàn)世鐵骨男兒楷模。  	#define ADVANEING   0
#define ASSAULTING  1
#define RESTING      2
Class Army
{
Private:
int m_iState;
int m_iEmptyCout;
public:
Army():m_iState(RESTING){}
void Advance();
void Assault();
void Rest();
};
void Army::Advance()
{
If (m_iState ==  ADVANEING   )
{
Cout << “Are Advaning!” << endl;
}
else if ( m_iState == ASSAULTING )
{
Cout << “sorry! Are assauling!Can’t Advace” << endl;
}
else if( m_iState == RESTING )
{
m_iState = ADVANING
Cout << “ok!Go!” << endl;
}
}
void Army:: Assault ()
{
If (m_iState ==  ADVANEING   )
{
m_iEmptyCout = 100;
m_iState == ASSAULTING;
Cout << “ok!Assault!” << endl;
}
else if ( m_iState == ASSAULTING )
{
m_iEmptyCount -= 100;
Cout << “Are assauling!” << endl;
}
else if( m_iState == RESTING )
{
m_iEmptyCout = 100;
m_iState = ASSAULTING;
Cout << “ok! Assault!” << endl;
}
}
void Army:: Rest ()
{
If (m_iState ==  ADVANEING   )
{
m_iState == RESTING;
Cout << “ok!Rest!” << endl;
}
else if ( m_iState == ASSAULTING )
{
Cout << “Are assauling!can’t Rest” << endl;
}
else if( m_iState == RESTING )
{
Cout << “Are Resing!” << endl;
}
}
好了這樣我們的類(lèi)就完成了,雖然看起來(lái)有些雜亂,但運(yùn)行應(yīng)該沒(méi)有什么問(wèn)題。這樣完成雖說(shuō)土了一些,但事實(shí)上并不影響它的正常運(yùn)行。但我們需要考慮的一個(gè)問(wèn)題是:當(dāng)需求變化的時(shí)候,我們的程序該如何去改?軟件界的一個(gè)規(guī)律就是需求一直在變更,變更伴隨著軟件的生存到死亡的過(guò)程。如今流行的設(shè)計(jì)模式,重構(gòu),測(cè)試驅(qū)動(dòng)開(kāi)發(fā)等技術(shù)目的都是為了適應(yīng)需求的變更,而將程序修改的難度降到最低來(lái)。所以我們來(lái)考慮這樣的情況,由于驃騎將軍取得了大勝,舉行了祭天儀式,祭天儀式中戰(zhàn)士興奮度提高,殺敵熱情暴增。所以驃騎決定將這個(gè)儀式加入到戰(zhàn)斗安排中,當(dāng)取得勝利的時(shí)候,舉行祭天儀式。而這又是一個(gè)新的狀態(tài),該狀態(tài)只有在Rest狀態(tài)下才能切換過(guò)去,我們?cè)撊绾稳バ薷某绦蚰??以目前的做法,我們需要在每個(gè)函數(shù)中添加條件,修改函數(shù),這樣又與我們?cè)诓呗阅J街刑岬降囊?guī)則“一個(gè)模塊對(duì)擴(kuò)展應(yīng)該是開(kāi)放的,而對(duì)修改應(yīng)該是關(guān)閉的”背道而馳了。怎么解決呢?還是同樣的方法:提煉出一個(gè)類(lèi)。同樣為了解決動(dòng)態(tài)改變狀態(tài)的需求,我們還應(yīng)該記著另一個(gè)規(guī)則:盡量針對(duì)接口編程,而不要針對(duì)實(shí)現(xiàn)編程。閑言少敘,我們還是看類(lèi)圖,這樣來(lái)的快一些。從類(lèi)圖,我們可以看到Army類(lèi)中擁有一個(gè)Station類(lèi)的對(duì)象,它所有的操作將通過(guò)該對(duì)象來(lái)實(shí)現(xiàn)。是不是發(fā)覺(jué)和策略模式很相似?先不說(shuō)這個(gè),我們先看完例子再說(shuō)??纯淳唧w代碼: 我們首先看以下State接口,很簡(jiǎn)單,就是幾個(gè)純虛函數(shù)。 class State
{
public:
virtual void Advance() = 0;
virtual void Assault() = 0;
virtual void Rest() = 0;
virtual void Fiesta() = 0;
};
我們?cè)賮?lái)看一下AdvanceState,我們看到在AdvanceState中有一個(gè)Army對(duì)象的指針,是因?yàn)樾枰趦?nèi)部修改狀態(tài),具體的代碼中可以看到。class AdvanceState : public State
{
private:
Army *m_pArmy;
public:
AdvanceState(Army *pArmy);
virtual void Advance();
virtual void Assault();
virtual void Rest() ;
virtual void Fiesta();
};
我們?cè)賮?lái)看一下AdvanceState的具體實(shí)現(xiàn):AdvanceState::AdvanceState(Army *pArmy):m_pArmy(pArmy){}
void AdvanceState::Advance()
{
cout << "Be in Advancing!" << endl;
}
void AdvanceState::Assault()
{
//設(shè)置假想的敵人數(shù)
m_pArmy->SetEmptyCount(200);
cout << "Ok!Assault!" << endl;
m_pArmy->SetState(m_pArmy->GetAssaultState());
}
void AdvanceState::Rest()
{
cout << "OK!Rest!" << endl;
m_pArmy->SetState(m_pArmy->GetRestState());
}
void AdvanceState::Fiesta()
{
cout << "sorry!can‘t Fiesta!" << endl;
}
很簡(jiǎn)單了,就是根據(jù)當(dāng)前狀態(tài)來(lái)處理各個(gè)函數(shù)。我們看到有這樣的函數(shù)m_pArmy->SetState(m_pArmy->GetRestState());是用來(lái)修改Army所處的狀態(tài)的。在Army類(lèi)中,我們可以看到它的具體實(shí)現(xiàn)。其它幾個(gè)狀態(tài)類(lèi)的實(shí)現(xiàn)類(lèi)同,就不房到這里了,感興趣的可以到附件中自己找。我們?cè)賮?lái)看看Army類(lèi)的定義:	class State;
class Army
{
private:
State* m_pState;
//保存各個(gè)狀態(tài)指針便于使用,當(dāng)有新的狀態(tài)填加的時(shí)候,我們也需要在此處添加
State* m_pAdvanceState;
State* m_pAssaultState;
State* m_pRestState;
State* m_pFiestaState;
int m_iEmptyCount;
public:
Army();
void SetState(State *pState);
State* GetAdvanceState();
State* GetAssaultState();
State* GetRestState();
State* GetFiestaState();
void Advance();
void Assault();
void Rest();
void Fiesta();
void SetEmptyCount(int iEmptyCount){m_iEmptyCount = iEmptyCount;}
int GetEmptyCount(){return m_iEmptyCount;}
};
它的實(shí)現(xiàn):	Army::Army()
{
m_pAdvanceState = new AdvanceState(this);
m_pAssaultState = new AssaultState(this);
m_pRestState = new RestState(this);
m_pFiestaState = new FiestaState(this);
m_pState = m_pRestState;
m_iEmptyCount = 0;
}
void Army::SetState(State *pState)
{
m_pState = pState;
}
State* Army::GetAdvanceState() {return m_pAdvanceState;}
State* Army::GetAssaultState() {return m_pAssaultState;}
State* Army::GetRestState() {return m_pRestState;}
State* Army::GetFiestaState() {return m_pFiestaState;}
void Army::Advance() {m_pState->Advance();}
void Army::Assault() {m_pState->Assault();}
void Army::Rest() {m_pState->Rest();}
void Army::Fiesta() {m_pState->Fiesta();}
其實(shí)也沒(méi)什么了。很容易的理解的。不知道漢武時(shí)代有沒(méi)有過(guò)閱兵儀式,如果有,那就會(huì)又多一個(gè)狀態(tài),想想我們?cè)撊绾谓鉀Q?挺簡(jiǎn)單了,為State添加一個(gè)新的子類(lèi),并為它提供一個(gè)閱兵的啟動(dòng)方法,當(dāng)然相應(yīng)的子類(lèi)也需要添加。相應(yīng)的Army類(lèi)中也需要添加該方法。這樣做,我們只是擴(kuò)展了原有類(lèi)的方法,而不會(huì)去改動(dòng)它原有的功能。這樣就可以避免給原有功能帶來(lái)bug了。 再看看該類(lèi)的調(diào)用:	int main(int argc, char* argv[])
{
Army army;
army.Advance();
army.Assault();
army.Rest();
army.Fiesta();
army.Assault();
army.Assault();
army.Rest();
army.Fiesta();
system("pause");
return 0;
}
創(chuàng)建對(duì)象后,我們可以直接調(diào)用它的函數(shù)來(lái)實(shí)現(xiàn)狀態(tài)的轉(zhuǎn)換了。好了,狀態(tài)模式,我們先講到這里了?;叵胍幌律匣氐牟呗阅J?,是不是覺(jué)得很象?在《Head First Design Model》中,該模式開(kāi)篇的扉頁(yè)上畫(huà)的是一幅煽情的母親流淚的圖片,說(shuō)她眼瞅著自己的孩子分離,此處的兩個(gè)孩子就是策略模式和狀態(tài)模式。我們可以這兩個(gè)模式的原理都是將一個(gè)類(lèi)中的屬性提煉成一個(gè)接口,再通過(guò)該接口實(shí)現(xiàn)對(duì)其子類(lèi)的調(diào)用而完成所屬類(lèi)的功能。它們的不同是狀態(tài)模式的接口的變化是在接口子類(lèi)中完成的,而策略模式是通過(guò)所屬類(lèi)來(lái)完成的。差別只是這一點(diǎn),具體工作中使用哪個(gè)模式,那就的具體問(wèn)題具體分析了。你只需記住面向?qū)ο笤O(shè)計(jì)的規(guī)則,就可以以不變應(yīng)萬(wàn)變了。 
 參考書(shū)目 
 | 
|  | 
來(lái)自: kyo_siye > 《亂砍設(shè)計(jì)模式系列》