[设计模式]行为模式-状态模式(C++描述)

 [设计模式]行为模式-状态模式(C++描述)

second60 20180509

1. 什么是状态模式

对于一些人或事特,会有不同状态,而一个状态会在不同的表现下转移到下一个状态。

通常情况下,我们可能写个if..else语句进行判断,或switch语句进行判断,但是当状态越来越多时,代码将变得不可维护,可读性和扩展性变得很差。同时,状态逻辑和动作逻辑没有分离。而状态模式正是解决这样的问题。


状态模式,使我们把状态逻辑动作实现分离出来,每个状态封装到一个类中。

 

2. 状态模式结构图

 

 

2.1 分析

1. 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。

2. 状态抽象类:定义状态的抽象接口,封装与Context相关的接口

3. 具体状态类:每一个子类实现一个状态相关的行为。

2.2 代码实现

class  Context;
// 状态父类
class  State
{
public:
virtual ~State(){}
virtual void OperationInterface(Context* context) = 0;
virtual void OperationChangeState(Context* context) = 0;
protected:
bool ChangeState(Context* context,State* state)
{
context->ChangeState(st);
}
};
// 具体状态类
class  ConcreteStateA: public State
{
public:
void OperationInterface(Context* context)
{
//doing
}

void OperationChangeState(Context* context)
{
OperationInterface(context);
this->ChangeState(context, new ConcreteStateB());
}
};

// 具体状态类
class  ConcreteStateB: public State
{
public:
void OperationInterface(Context* context)
{
//doing
}

void OperationChangeState(Context* context)
{
OperationInterface(context);
this->ChangeState(context, new ConcreteStateA());
}

};

//环境类
class Context
{
public:
Context(State* state){_state = state;}
~Context(){delete _state;}
bool ChangeState(State* state)
{
this->_state = state;
return true;
}

void OperationInterface()
{
_state->OperationInterface(this);
}

void OperationChangeState()
{
_state->OperationChangeState(this);
}

private:
friend class State;
State* _state;
};

int main()
{
State* st = new ConcreteStateA();
Context* con = new Context(st);
con->OperationChangeState();
con->OperationChangeState();
con->OperationChangeState();
//释放
return 0;
}

2.3 优点

1. 对象的状态逻辑和动作实现分离,状态分布在不同子类中

2. 封装了转换规则

3. 枚举了可能的状态,确定了状态的种类

4. 将所有与某个状态有关的行为放到了一个类中,方便增加新的状态

5. 多个环境对象可共享一个状态对象,减少对象的个数

2.4 缺点

1. 因为状态分布在不同子类中,所以整体状态图的理解成本大

2. 会增加系统类和对象的个数

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

4. 新增状态,可能会修改相互转换的其他状态

 

2.5 状态模式和策略模式

状态模式和策略模式结构图很相似,但两者的用途不同。

状态模式主要适应对象状态改变时的不同处理策略

策略模式为具体算法和实现接口的解耦

 

 

3 适用场景

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

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

 

4 例子

1: 电梯的状态:开门,关门,停,运行

代码:

// 四种状态
enum ELiftState
{
ELiftState_Open		= 1,
ELiftState_Close	= 2,
ELiftState_Stop		= 3,
ELiftState_Run		= 4,
};

//电梯状态抽象类
class LiftState
{
public:
LiftState(){}
void setContext(Context* context){_context = context;}
virtual ~LiftState(){}
virtual void open() = 0;
virtual void close() = 0;
virtual void stop() = 0;
virutal void run() = 0;
private:
Context* _context;
};
// 具体状态类
class OpenningState:public LiftState
{
public:
OpenningState(Context* context):LiftState(context){}
void close()
{
this->_context->setLiftState(ELiftState_Close);
this->_context->getLiftState()->close();
}
void open()
{
 	cout << “continue openning” << endl;
}
void run(){}
void stop(){}
};
// 具体状态类
class ClosingState:public LiftState
{
public:
ClosingState(Context* context):LiftState(context){}
void close()
{
cout << “continue closing” << endl;
}
void open()
{
this->_context->setLiftState(ELiftState_Open);
this->_context->getLiftState()->open();
}
void run()
{
this->_context->setLiftState(ELiftState_Run);
this->_context->getLiftState()->run();
}
void stop()
{
this->_context->setLiftState(ELiftState_Stop);
this->_context->getLiftState()->stop();
}
};

// 具体状态类
class RunningState:public LiftState
{
public:
RunningState(Context* context):LiftState(context){}
void close(){}
void open(){}
void run()
{
cout << “keep running” << endl;
}
void stop()
{
this->_context->setLiftState(ELiftState_Stop);
this->_context->getLiftState()->stop();
}
};
class StoppingState:public LiftState
{
public:
StoppingState(Context* context):LiftState(context){}
void close(){}
void open()
{
this->_context->setLiftState(ELiftState_Open);
this->_context->getLiftState()->open();
}
void run()
{
this->_context->setLiftState(ELiftState_Run);
this->_context->getLiftState()->run();
}
void stop()
{
cout << “keep stop”<< endl;
}
};

class Context
{
public:
Context(){}
void setLiftState(LiftState* state)
{
_now_state = state;
state->setContext(this);
}
void open(){_now_state->open();}
void close(){_now_state->close();}
void run(){_now_state->run();}
void stop(){_now_state->stop();}
private:
LiftState * _now_state;
};

int main()
{
Context* context = new Context();
context->setLiftState(new ClosingState());
context->open();
context->close();
context->run();
context->stop();
}

5 总结

状态模式,把状态逻辑和动作分离,状态在状态子类中,动作在Context中.两者互相变化独立即,改变状态逻辑可以很容易复用Context的动作,也可以在不影响State派生类的前提下创建Context子类来更改或替换动作。

状态模式使用比较广泛,凡是涉及到状态转换,或分支判断的,都可以采用状态模式,但在有适用的情况下使用。

 

下节预告:观察都模式

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值