C++设计模式 之 “状态变化” 模式:State、Memento

时间:2023-03-09 07:57:57
C++设计模式 之 “状态变化” 模式:State、Memento

  “状态变化”模式

  在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一问题提供了一种解决方案。
  典型模式
  # state
  # memento

  Part 1 State 状态模式
  动机
  #在软件构建过程中,某些对象的状态如果改变,其行为也会随之而变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
  #如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?
  #避免代码的坏味道——Long Method
  模式定义
  允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。——《设计模式》GoF
  结构
C++设计模式 之 “状态变化” 模式:State、Memento 

  结构 from 《大话设计模式》

C++设计模式 之 “状态变化” 模式:State、Memento

  代码 未使用State模式 from 《大话设计模式》

 void work(int clock, TASK_FINISH task) {
if (clock < )
{
cout << "上午"<<endl;
}
else if (clock < )
{
cout << "中午" << endl;
}
else if (clock < )
{
cout << "下午" << endl;
}
else
{
if (task == true)
{
cout << "下班" << endl;
}
else
{
if (clock < )
{
cout << "晚上,加班" << endl;
} cout << "好累,睡着了" << endl;
}
}
} int main() { work(, false);
work(, false);
work(, false);
work(, false); return ;
}

  代码 State模式 from 《大话设计模式》

 #include <string>
#include <iostream> using namespace std; struct Context;
struct State {
virtual void work(Context c) = ;
}; struct Context {
bool taskFinish = false;
unsigned clock = ;
State* _state;
void work() { this->_state->work(*this); }
}; struct SleepState : public State {
virtual void work(Context c) override {
cout << "sleeping..." << endl;
}
}; struct EveningState : public State {
virtual void work(Context c) override {
if (c.taskFinish == true)
cout << "back home" << endl;
else
{
if (c.clock < )
cout << "evening" << endl;
else
c._state = new SleepState();
}
}
}; struct AfternoonState : public State {
virtual void work(Context c) override {
if (c.clock < )
cout << "afternoon" << endl;
else
c._state = new EveningState();
}
}; struct NoonState : public State {
virtual void work(Context c) override {
if (c.clock < )
cout << "noon" << endl;
else
c._state = new AfternoonState();
}
}; struct ForenoonState : public State {
virtual void work(Context c) override {
if (c.clock < )
cout << "forenoon" << endl;
else
c._state = new NoonState();
}
}; int main() {
Context project;
project._state = new ForenoonState(); project.work(); project.clock = ;
project.work(); project.clock = ;
project.work(); project.clock = ;
project.work(); return ;
}

  要点总结
  #State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
  #为不同的状态引入不同的对象,使得状态转化变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换时原子性的——即要么彻底转换过来,要么不转换。
  #如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。