意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
适用性
- 一个对象的行为取决于它的状态。并且它必须在运行时刻根据状态改变它的行为。
- 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。
类图
例子场景
有一个糖果机,一个糖果25分线,机器有四种状态,分别是没有25分钱,有25分钱,糖果售罄,售出糖果,可以进行的动作有投入25分钱,返回25分钱,转动曲柄,发放糖果,设计一个框架,可以方便管理和添加状态,不要使用条件语句实现。
实现
State.h
#pragma once
class GumballMachine;
class State
{
public:
State();
virtual void insertQuarter() = 0;
virtual void ejectQuarter() = 0;
virtual void turnCrank() = 0;
virtual void dispense() = 0;
protected:
GumballMachine* m_pGumballMachine;
};
State.cpp
#include "State.h"
State::State()
: m_pGumballMachine(nullptr)
{
}
SoldState.h
#pragma once
#include "State.h"
class GumballMachine;
class SoldState : public State
{
public:
SoldState(GumballMachine* pGumballMachine);
void insertQuarter() override;
void ejectQuarter() override;
void turnCrank() override;
void dispense() override;
};
SoldState.cpp
#include "SoldState.h"
#include <GumballMachine.h>
#include <iostream>
using namespace std;
SoldState::SoldState(GumballMachine* pGumballMachine)
{
m_pGumballMachine = pGumballMachine;
}
void SoldState::insertQuarter()
{
cout << "Please wait, we are already giving you a gumball" << endl;
}
void SoldState::ejectQuarter()
{
cout << "Sorry, You already turned the crank" << endl;
}
void SoldState::turnCrank()
{
cout << "Turning twice does not get you another gumball" << endl;
m_pGumballMachine->setState(m_pGumballMachine->getNoQuarterState());
}
void SoldState::dispense()
{
cout << "dispense" << endl;
}
NoQuarterState.h
#pragma once
#include "State.h"
class GumballMachine;
class NoQuarterState : public State
{
public:
NoQuarterState(GumballMachine *pGumballMachine);
void insertQuarter() override;
void ejectQuarter() override;
void turnCrank() override;
void dispense() override;
};
NoQuarterState.cpp
#include "NoQuarterState.h"
#include "GumballMachine.h"
#include <iostream>
using namespace std;
NoQuarterState::NoQuarterState(GumballMachine* pGumballMachine)
{
m_pGumballMachine = pGumballMachine;
}
void NoQuarterState::insertQuarter()
{
cout << "You inserted a quarter" << endl;
m_pGumballMachine->setState(m_pGumballMachine->getSoldState());
}
void NoQuarterState::ejectQuarter()
{
cout << "You have not inserted a quarter" << endl;
}
void NoQuarterState::turnCrank()
{
cout << "You turned, but there is no quarter" << endl;
}
void NoQuarterState::dispense()
{
cout << "You need to pay first" << endl;
}
GumballMachine.h
#pragma once
#include <memory>
class State;
class GumballMachine
{
public:
GumballMachine();
void insertQuarter();
void ejectQuarter();
void turnCrank();
void dispense();
void setState(State* pState) { m_pCurrentState = pState; }
State* getNoQuarterState() { return m_pNoQuarterState.get(); }
State* getSoldState() { return m_pSoldState.get(); }
private:
std::shared_ptr<State> m_pNoQuarterState;
std::shared_ptr<State> m_pSoldState;
State* m_pCurrentState;
};
GumballMachine.cpp
#include "GumballMachine.h"
#include "State.h"
#include "NoQuarterState.h"
#include "SoldState.h"
GumballMachine::GumballMachine()
: m_pNoQuarterState(std::make_shared<NoQuarterState>(this))
, m_pSoldState(std::make_shared<SoldState>(this))
, m_pCurrentState(getNoQuarterState())
{
}
void GumballMachine::insertQuarter()
{
m_pCurrentState->insertQuarter();
}
void GumballMachine::ejectQuarter()
{
m_pCurrentState->ejectQuarter();
}
void GumballMachine::turnCrank()
{
m_pCurrentState->turnCrank();
}
void GumballMachine::dispense()
{
m_pCurrentState->dispense();
}
main.cpp
#include "GumballMachine.h"
#include <iostream>
using namespace std;
int main()
{
GumballMachine gumballMachine;
gumballMachine.insertQuarter();
gumballMachine.ejectQuarter();
gumballMachine.turnCrank();
gumballMachine.dispense();
cout << endl;
gumballMachine.insertQuarter();
gumballMachine.ejectQuarter();
gumballMachine.turnCrank();
gumballMachine.dispense();
return 0;
}