再次使用 IDE CodeGear C++Builder 2007
下載原始碼 - 6.18 KB
簡介
在本文中,我將使用良好的程式設計實踐來解釋狀態(State)設計模式的用法。本文以一個我們可以在不同時間間隔下開發的簡單問題——訊號燈——為例。
狀態模式
它被認為是行為型模式之一,其核心思想是允許一個物件在其內部狀態改變時改變其行為。
這裡我們可以看到狀態模式的類圖,圖中使用了合適的類名。
圖示解釋了各個參與者及其定義。
- 上下文(Context)| TLNetTraffic:此類可以包含不同的狀態。
- 狀態(State)| TLState:為所有具體狀態定義一個公共介面或抽象類,它們總是實現相同的介面或繼承自同一個抽象類。
- 具體狀態(ConcreteState)| TL {Red, Yellow, Green}:為每個具體狀態實現與上下文某一狀態相關聯的行為。
實現
我們必須具備足夠且必要的面向物件程式設計(OOP)知識,尤其是對指標的理解。
……我們定義了上下文類(Context Class),注意,它以紅燈(Red Light)狀態啟動。
¨TLNetTraffic.h¨
1 2 3 4 5 6 7 8 9
|
class TLNetTraffic
{
private:
TLState* _state;
public:
TLNetTraffic();
void setState ( TLState* state );
void Handle();
};
|
¨TLNetTraffic.cpp¨
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
TLNetTraffic::TLNetTraffic()
{
_state = new TLRed(this);
}
void TLNetTraffic::setState ( TLState* state )
{
_state = state;
}
void TLNetTraffic::Handle ()
{
_state->Handle();
}
|
……所有可實現的狀態都共用的抽象類,使用 Handle() 方法作為狀態切換的介面,該方法應由派生類重寫。
¨TLState.h¨
1 2 3 4 5
|
class TLState
{
public:
virtual void Handle() = 0;
};
|
……當然,每個狀態都是獨立的。請注意,這三個狀態的實現方式是相同的,但這並非總是如此,具體取決於每個狀態需要怎樣的實現。
¨TLRed.h¨
1 2 3 4 5 6 7 8 9
|
class TLRed: public TLState
{
private:
TLNetTraffic* _context;
public:
TLRed(TLNetTraffic* context);
void Handle();
};
|
¨TLRed.cpp¨
1 2 3 4 5 6 7
|
TLRed::TLRed(TLNetTraffic* context): _context(context) {};
void TLRed::Handle()
{
printf("Red Light\n");
_context->setState( new TLGreen(_context) );
}
|
¨TLGreen.h¨
1 2 3 4 5 6 7 8 9
|
class TLGreen: public TLState
{
private:
TLNetTraffic* _context;
public:
TLGreen(TLNetTraffic* context);
void Handle();
};
|
¨TLGreen.cpp¨
1 2 3 4 5 6 7
|
TLGreen::TLGreen(TLNetTraffic* context): _context(context) {};
void TLGreen::Handle()
{
printf("Green Light\n");
_context->setState( new TLYellow(_context) );
}
|
¨TLYellow.h¨
1 2 3 4 5 6 7 8 9
|
class TLYellow: public TLState
{
private:
TLNetTraffic* _context;
public:
TLYellow(TLNetTraffic* context);
void Handle();
};
|
¨TLYellow.cpp¨
1 2 3 4 5 6 7
|
TLYellow::TLYellow(TLNetTraffic* context): _context(context) {};
void TLYellow::Handle()
{
printf("Yellow Light\n");
_context->setState( new TLRed(_context) );
}
|
……再次是 main 函式。我們使用 <time.h> 庫來按時間間隔改變狀態。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
int main (int argc, char* argv[])
{
TLNetTraffic netTraffic;
int count = 0, i=0;
int seconds;
while(1)
{
if (i%3==0)
printf("---------\nSession %d\n---------\n", ((i+1)/3)+1 );
if (count == 0) seconds =6, count = 1;
else if (count == 1) seconds = 4, count = 2;
else if (count == 2) seconds = 5, count = 0;
sleep( (clock_t)seconds * CLOCKS_PER_SEC );
netTraffic.Handle();
i++;
}
return 0;
}
|
核心思想是按照時間間隔{紅燈(6秒),綠燈(4秒),黃燈(5秒)}無限迴圈地改變燈光狀態,模擬公路上任何交通訊號燈的正常工作,其中使用的某些資料可能不準確。
……當然少不了 sleep() 函式,它在每次迭代中維持時間間隔。
1 2 3 4 5 6
|
void sleep( clock_t wait )
{
clock_t goal;
goal = wait + clock();
while( goal > clock() );
}
|
將會產生如下輸出
---------
Session 1
---------
Red Light
Green Light
Yellow Light
---------
Session 2
---------
Red Light
Green Light
Yellow Light
---------
Session 3
---------
… and so on
|
結論
在當今所有的程式設計工作中,都應該正確使用各種反饋和已定義的設計模式。在我們的實現中,透過運用模式和技巧解決了一個問題,其能力得以體現。幸運的是,我會繼續為大家努力。
關於設計模式的推薦書目
- Steve Holzner, PhD. (2006). Design Patterns for Dummies.(《設計模式傻瓜書》)
- Eric Freeman, Elizabeth Freeman, Kathy Sierra, Bert Bates. (2004). Your Brain on Design Patterns Head First Design Patterns.(《深入淺出設計模式》)
- James W. Cooper. (2000). JAVATM Design Patterns : A Tutorial.(《Java設計模式:教程》)
- Erich Gamma, Richard Helm, Ralph Johnson, Jhon Vlissides. (1998). Design Patterns. Gang of Four.(《設計模式》,“四人幫”)