您的位置:首页 > 编程语言 > C语言/C++

设计模式---状态模式(C++实现)

2017-03-20 10:23 483 查看
        在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。在状态模式中,通过创建不同的状态对象和一个随着状态变化的context对象。

意图

        允许对象在内部状态发生改变时,改变它的行为,对象看起来好像修改了它的类。

解决问题

        对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。

如何解决

        将各种具体的状态类抽象出来

优点

 1. 封装了转换规则

 2. 枚举可能的状态,在枚举状态之前需要确定确定状态种类

 3. 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为

 4.允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块

 5. 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数

缺点

1. 状态模式的使用必然会增加系统类和对象的个数

2. 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱

3. 添加新的状态需要修改那些负责转换的源代码,否则无法转换到新增的状态,而且修改某个状态的行为也要修改源代码

使用场景

        1. 行为随状态改变而改变的场景

        2. 条件、分支语句的代替者

注意事项

        在行为受约束的时候使用状态模式,而且状态不超过5个

UML类图



C++实现

    例子:实现A 和 B状态转换



     这里利用状态模式来实现,具体状态就是状态A与状态B,然后上下文存在一个“转换状态”的方法。之后状态A与状态B共同接口就是抽象状态State。

code:

//状态模式

class Context; //类,上下文,的提前引用,主要是用于通过C++的编译,需要提前声明这个类

class State //抽象状态
{
public:
virtual void switch_state() = 0;
};
//每一个具体状态,都必须有私有变量上下文Context *context;
//每一个具体状态的构造方法,都必须用this->context=context;实现将自己注册到上下文中。
//不得在每一个具体状态中实现转换状态的方法switch_state(),只能在类外实现,因为C++禁止类的互相调用,
//否则会出现error C2027: 使用了未定义类型的错误
class StateA : public State //具体状态
{
public :
StateA(Context * _context)
:context(_context)
{}
void switch_state();

private:
Context *context;
};

class StateB :public State
{
public :
StateB(Context * _context)
:context(_context)
{}
void switch_state();

private:
Context * context;
};

class Context
{
State *stateA, *stateB, *state;
public :
Context()
:stateA(new StateA(this))
, stateB(new StateB(this))
, state(stateA)
{}

void switch_state()
{
state->switch_state();
}

void SetState(State* _state)
{
state = _state;
}

State* getStateA()
{
return stateA;
}

State* getStateB()
{
return stateB;
}

};

//实现具体状态中,对应的转换方法
void StateA::switch_state()
{
context->SetState(context->getStateB());
cout << "已转换到状态B " << endl;
}
void StateB::switch_state()
{
context->SetState(context->getStateA());
cout << "已转换到状态A" << endl;
}

客户端:
int test_State() //状态模式
{
Context* context = new Context();
context->switch_state();
context->switch_state();
context->switch_state();
context->switch_state();

delete context;
context = NULL;

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息