小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

亂砍設(shè)計(jì)模式之二-STATE

 kyo_siye 2007-04-13

源代碼下載
  STATE模式的中文名稱(chēng)是狀態(tài)模式。在《設(shè)計(jì)模式》一書(shū)中的定義是:允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變的時(shí)候改變它的行為。對(duì)象看起來(lái)似乎修改了它的類(lèi)(中文譯書(shū)上的原話,不過(guò)我覺(jué)得這句話應(yīng)該翻譯成——對(duì)象顯現(xiàn)出來(lái)的是改變了它所屬的類(lèi))。看了定義還是感覺(jué)有些抽象,好的,我們還是通過(guò)一個(gè)例子來(lái)學(xué)習(xí)該模式。還是先從情節(jié)設(shè)計(jì)開(kāi)始:

嚴(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)世鐵骨男兒楷模。
  前年看到的一部連續(xù)劇《漢武大帝》,總體感覺(jué)還行。不過(guò)太過(guò)小氣,為了一些戲劇效果,把很多歷史事件強(qiáng)塞了進(jìn)去。如曹操為人捉刀的故事,被安排到了漢武帝身上;為了那么一段冒頓單于鳴鏑殺父的情節(jié),讓他晚生了數(shù)十年,居然他還成了漢武帝的死敵(為漢武帝安排這么一個(gè)對(duì)手,我總覺(jué)得太小覷了漢武帝)。
  還有些事,本不想寫(xiě)了,后來(lái)想想還是寫(xiě)吧。反正咱這是亂砍,就隨性而來(lái)吧。網(wǎng)上有個(gè)臭名昭著的網(wǎng)站,叫做漢網(wǎng)。集聚著一群民族主義分子,提倡漢服(不過(guò)他們好像也不是提倡每天都穿),說(shuō)這樣可以幫助中國(guó)人恢復(fù)民族自尊心。讓我想起阿Q說(shuō)過(guò)的:老子原前也闊過(guò)。還有明顯意淫古人的意味,翻看歷史,我們可以看到武帝之前,漢族一直受匈奴人的欺凌。而武帝之后,國(guó)力衰落,雖然周邊的小國(guó)還算順?lè)?,但漢朝還是失去了武帝時(shí)的雄霸之氣。試想想如果當(dāng)時(shí)情況下的皇帝不是漢武,而是一個(gè)軟弱無(wú)能,如明朝的那個(gè)建文帝,估摸著漢朝內(nèi)部都搞不定。更甭談打擊匈奴了,而消滅匈奴取得成功,也和武帝破格提拔的將領(lǐng)有關(guān)。試想沒(méi)有衛(wèi)青,霍去病又會(huì)是什么情況?第一次攻擊匈奴,四路人馬出擊,兩路被?。ㄖ娘w將軍李廣被俘,而后逃脫),一路無(wú)功,只有衛(wèi)青有所斬獲。而后的多次出擊中,除衛(wèi)青,霍去病外的其他將領(lǐng)多有敗績(jī)。在電視《漢武大帝》中,李廣的死被安排成了為了成全衛(wèi)青的計(jì)策,吸引匈奴,他主動(dòng)陷于匈奴包圍圈中,英勇戰(zhàn)死(這段情節(jié),描寫(xiě)的匈奴人也太弱智了)。我一哥們看到這情節(jié)后,哈哈大笑。然后他津津有味的為別人講解李廣真正的死因:李廣是路癡死的。李廣出擊匈奴的戰(zhàn)爭(zhēng)中多次迷路,最后一次因?yàn)樾l(wèi)青派人問(wèn)他迷路的原因,李廣自殺身亡。李廣是漢朝名將,但我覺(jué)得他不適合那個(gè)年代。從戰(zhàn)國(guó)時(shí)代起,名將都以智略取勝。因?yàn)閼?zhàn)爭(zhēng)基本都以攻城拔地的形式進(jìn)行,都有相對(duì)固定的戰(zhàn)爭(zhēng)場(chǎng)地。武器也以戰(zhàn)車(chē),重騎兵為主,行動(dòng)較為緩慢,主要打的是陣地戰(zhàn)。而當(dāng)時(shí)匈奴,采取的是打得過(guò)就打,打不過(guò)就跑得游擊套路(呵呵,應(yīng)該是我軍游擊戰(zhàn)的雛形了)。面對(duì)這樣的對(duì)手,更需要的就是霍去病這種有銳氣,深沉勇猛,敢于追著敵人背后猛打的將領(lǐng)(我覺(jué)得國(guó)民黨將領(lǐng)薛岳也屬于此類(lèi)戰(zhàn)將)。當(dāng)漢武讓霍去病學(xué)習(xí)古兵法的時(shí)候,他的回答是:顧方略何如耳,不至學(xué)古兵法。也許正是這種藐視權(quán)威的氣概成就了霍去病,也成就了“犯大漢者,雖遠(yuǎn)必誅”的大漢豪情。但這段歷史的演繹里離不開(kāi)漢武帝,也離不開(kāi)霍去?。☉?zhàn)功最著的是他,單靠衛(wèi)青可能這場(chǎng)戰(zhàn)爭(zhēng)很難如此徹底),是他們的組合成就了這段歷史。沒(méi)有這樣的組合,也許大漢天下會(huì)被匈奴的鐵蹄踐踏,而漢文明也許會(huì)象希臘文明那樣被游牧民族踐踏而消亡。歷史充滿了偶然性,歷史本身并不值得我們拿來(lái)炫耀。我覺(jué)得如今的中國(guó)人沒(méi)有什么不自信的,我也不覺(jué)得現(xiàn)在的中國(guó)人沒(méi)古代好,偉大的時(shí)代總離不開(kāi)偉大的人物。也許我們的民族只是現(xiàn)在缺少一個(gè)這樣的人物,那也就不好怨天尤人了,因?yàn)樯硖庍@個(gè)時(shí)代的我們,沒(méi)有一個(gè)是偉人,我不是,你也不是,那你怪誰(shuí)去?好了,不扯了,還是認(rèn)真做我們的Coding生涯吧。
  我們以驃姚將軍深入漠北追殲匈奴人的情節(jié)作為我們的例子,這次我們將五萬(wàn)騎兵作為我們的對(duì)象。這五萬(wàn)騎兵作為一個(gè)作戰(zhàn)整體,會(huì)有一些這樣的一些狀態(tài):休整,前進(jìn),攻擊。整個(gè)作戰(zhàn)過(guò)程中都在這些狀態(tài)下進(jìn)行著。我們先來(lái)看看下圖:



  這里我們看到一個(gè)轉(zhuǎn)換圖:共有三種狀態(tài)Advaneing(前進(jìn)),Assaulting(攻擊狀態(tài)),Resing(休息狀態(tài))。三個(gè)狀態(tài)之間可以進(jìn)行轉(zhuǎn)換,Advaneing和Resing可以直接轉(zhuǎn)換,Advanceing和Resing可以直接轉(zhuǎn)換到Assaulting狀態(tài),而Assaulting只能在敵軍被全殲的時(shí)候才能轉(zhuǎn)化到Resing狀態(tài)。
  如何來(lái)實(shí)現(xiàn)該系統(tǒng)呢?我們還是首先用土鱉似的方式來(lái)實(shí)現(xiàn)第一個(gè)系統(tǒng),這樣更有助于看到模式的優(yōu)點(diǎn)。我們首先建立一個(gè)Army類(lèi),如下:

	#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ū)目

  • 設(shè)計(jì)模式——可復(fù)用面向?qū)ο筌浖幕A(chǔ)(Design Patterns ——Elements of Reusable Object-Oriented Software) Erich Gamma 等著 李英軍等譯 機(jī)械工業(yè)出版社
  • Head First Design Patterns(影印版)Freeman等著 東南大學(xué)出版社
  • 道法自然——面向?qū)ο髮?shí)踐指南 王詠武 王詠剛著 電子工業(yè)出版社
  • 史記 網(wǎng)上找到的電子檔

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多