State(状态)模式的目的是解决当控制一个对象状态转换的条件表达式过于复杂时的问题。它把状态的判断逻辑转移到一系列各自独立的类中,从而把复杂的条件分支简单化。每个具体状态用一个类来表示,但这也意味着状态逻辑会分散到很多子类中,维护成本相应提高。

与策略模式最大的区别在于:State 模式将 State 声明为 Contex 的友元类,从而让状态对象能够访问 Context 的私有成员,完成状态切换。

问题场景

当需要用 switch-case 来决定多个状态时(有限状态自动机),常见的两个问题是:

  1. 如果 case 分支太多,代码迅速膨胀;
  2. case 的判断逻辑与具体实现混在一起,很难维护和扩展。

例1:通用状态机示例

头文件
                	class State;
                
                	class Contex
                	{
                	public:
                		Contex(State*state);
                		void OperationInterface();
                		void Print();
                	private:
                		void ChangeState(State*state);
                		State*state = nullptr;
                		friend class State;
                
                	};
                
                	class State
                	{
                	public:
                		virtual void PrintState() = 0;
                		virtual	void OperationInterface(Contex *contex) = 0;
                	protected:
                		void ChangeState(Contex*contex, State*state);
                
                	};
                
                	class ConCreateStateA :public State
                	{
                	public:
                		virtual void OperationInterface(Contex *contex)override;
                		virtual void PrintState() override;
                	};
                
                	class ConCreateStateB :public State
                	{
                	public:
                		virtual void OperationInterface(Contex *contex)override;
                		virtual void PrintState() override;
                	};
                
                
                
                	void testState2();
                
                
                源文件
                	void  Contex::Print()
                	{
                		state->PrintState();
                	}
                	void Contex::OperationInterface()
                	{
                		state->OperationInterface(this);
                	}
                
                
                	void  Contex::ChangeState(State*state)
                	{
                		this->state = state;
                	}
                
                	Contex::Contex(State*state)
                	{
                		this->state = state;
                	}
                
                
                	void State::ChangeState(Contex*contex, State*state)
                	{
                		contex->ChangeState(state);
                	}
                
                	void  ConCreateStateA::PrintState()
                	{
                		cout << "current is A" << endl;
                	}
                	void ConCreateStateA::OperationInterface(Contex *contex)
                	{
                		this->ChangeState(contex, new ConCreateStateB);
                	}
                
                
                
                	void  ConCreateStateB::OperationInterface(Contex *contex)
                	{
                		this->ChangeState(contex, new ConCreateStateA);
                	}
                
                
                	void  ConCreateStateB::PrintState()
                	{
                		cout << "current is B" << endl;
                	}
                
                
                
                	void testState2()
                	{
                
                		Contex *contes = new Contex(new ConCreateStateA);
                		contes->Print();
                		contes->OperationInterface();
                
                		contes->Print();
                		contes->OperationInterface();
                
                		contes->Print();
                		contes->OperationInterface();
                	}

例2:电灯开关示例

头文件
                #pragma  once
                
                #include "PublicHeaders.h"
                
                
                namespace s1
                {
                
                	class Light;
                
                	class SwitchState
                	{
                	public:
                		virtual void PressSwitch(Light *light) = 0;
                		virtual void PrintState() = 0;
                	protected:
                		void OnChangeState(Light*light, SwitchState* state);
                	};
                
                
                	class On :public SwitchState
                	{
                	public:
                		virtual void PressSwitch(Light *light);
                		virtual void PrintState();
                
                	};
                	class Off :public SwitchState
                	{
                
                		virtual void PressSwitch(Light *light);
                
                		virtual void PrintState();
                
                
                
                	};
                
                
                	class Light
                	{
                	public:
                		Light(SwitchState *state);
                
                		void PressSwitch();
                		void PrintCurrent();
                	private:
                		SwitchState* state = nullptr;
                		friend class SwitchState;
                	};
                
                
                
                	void testState();
                }
                
                
                
                源文件
                #include "State.h"
                
                namespace s1
                {
                
                	void SwitchState::OnChangeState(Light*light, SwitchState* state)
                	{
                		if (light->state)
                		{
                			delete light->state;
                		}
                		light->state = state;
                	}
                
                
                	void On::PressSwitch(Light *light)
                	{
                		this->OnChangeState(light, new Off);
                
                	}
                
                	void  On::PrintState()
                	{
                		cout << "current is on" << endl;
                	}
                
                
                
                	void  Off::PressSwitch(Light *light)
                	{
                		this->OnChangeState(light, new On);
                
                	}
                
                	void Off::PrintState()
                	{
                		cout << "current is off" << endl;
                	}
                
                
                
                	Light::Light(SwitchState *state)
                	{
                		this->state = state;
                	}
                
                	void 	Light::PressSwitch()
                	{
                		state->PressSwitch(this);
                	}
                	void 	Light::PrintCurrent()
                	{
                		state->PrintState();
                	}
                
                
                	void testState()
                	{
                		Light *light = new Light(new Off);
                
                
                		light->PrintCurrent();
                		light->PressSwitch();
                
                
                		light->PrintCurrent();
                		light->PressSwitch();
                
                		light->PrintCurrent();
                		light->PressSwitch();
                
                		light->PrintCurrent();
                
                
                	}
                }