再次使用 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.(《设计模式》,“四人帮”)