目录
1.意图
State pattern属于行为型模式。
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
简单来说,就是将 “一个大 class + 一堆 if else” 替换为 “一堆小 class”。一堆小 class 就是一堆状态,用一堆状态代替 if else 会更好拓展与维护。
在实际工程代码中,一般是用FSM(有限状态机)来实现。FSM在许多不同的情况下用于建模复杂的实体状态。
2.UML类图
3.GOF角色说明
Context:定义客户感兴趣的接口;维护一个ConcreteState子类的实现。
State:状态接口,即定义一个接口以封装与Context的一个特定状态相关的行为。
ConcreteState subclasses:具体状态子类。每一个子类实现一个与Context的一个状态相关的行为。
4.代码实现
下面例子模拟银行卡的存/取钱流程,客户的帐号状态,随着余额改变而不断变化。
GreenState(余额充足)----状态迁移---->YellowState(收支平衡)----状态迁移---->RedState(透支)---->状态迁移---->GreenState/YellowState,不断循环。
头文件fsm.h实现:
#pragma once
#include <string>
//前向声明
class Depositor;
//UML中的"State"抽象类
class State
{
public:
//当前状态
std::string GetCurrState() const { return _currState; }
//储户id
Depositor* GetDepositor() const { return _depositor; }
void SetDepositor(Depositor* dp) { _depositor = dp; }
//余额
double GetBalance() const { return _balance; }
void SetBalance(const double balance) { _balance = balance; }
virtual void Deposit(const double money) = 0; //存钱
virtual void Withdraw(const double money) = 0; //取钱
virtual void PayInterest() = 0; //利息
protected:
std::string _currState;
Depositor* _depositor;
double _balance;
double _interest;
double _lowerLimit;
double _upperLimit;
};
//UML中的"ConcreteState"类
//绿色状态, 余额充足
class GreenState : State
{
public:
GreenState(State* state);
void Deposit(const double money);
void Withdraw(const double money);
void PayInterest();
void TransferNextState(); //扭转到下一个状态
private:
GreenState();
void Initialize();
};
//UML中的"ConcreteState"类
//黄色状态, 收支基本平衡. 无透支, 但也没有太多余额
class YellowState : State
{
public:
YellowState(State* state);
YellowState(const double balance, Depositor* dp);
void Deposit(const double money);
void Withdraw(const double money);
void PayInterest();
void TransferNextState(); //扭转到下一个状态
private:
YellowState();
void Initialize();
};
//UML中的"ConcreteState"类
//红色状态,入不敷出,已透支
class RedState : State
{
public:
RedState(State* state);
void Deposit(const double money);
void Withdraw(const double money);
void PayInterest();
void TransferNextState(); //扭转到下一个状态
private:
RedState();
void Initialize();
double _serviceFee;
};
//UML中的"Context"类
//储户帐号和状态
class Depositor
{
public:
Depositor(const std::string id);
~Depositor();
double GetBalance() const;
void Deposit(const double money);
void Withdraw(const double money);
void PayInterest();
void SetState(State* state) { _state = state; }
State* GetState() { return _state; }
private:
State* _state;
const std::string _id;
Depositor();
};
main.cpp 主逻辑实现
#include <iostream>
#include "fsm.h"
Depositor::Depositor(const std::string id) : _id(id) {
//账户默认初始化为余额为0的黄色状态
_state = reinterpret_cast<State*>(new YellowState(0.0, this));
}
Depositor::~Depositor() {
if (_state != nullptr) {
delete _state;
_state = nullptr;
}
}
double Depositor::GetBalance() const {
return _state->GetBalance();
}
void Depositor::Deposit(const double money) {
_state->Deposit(money);
std::cout << "Deposited $" << money << std::endl;
std::cout << "Balance $" << GetBalance() << std::endl;
std::cout << "CurrStatus " << _state->GetCurrState() << std::endl;
std::cout << std::endl;
}
void Depositor::Withdraw(const double money) {
_state->Withdraw(money);
std::cout << "Withdraw $" << money << std::endl;
std::cout << "Balance $" << GetBalance() << std::endl;
std::cout << "CurrStatus " << _state->GetCurrState() << std::endl;
std::cout << std::endl;
}
void Depositor::PayInterest() {
_state->PayInterest();
std::cout << "------Interest Pay------" << std::endl;
std::cout << "Balance $" << GetBalance() << std::endl;
std::cout << "CurrStatus " << _state->GetCurrState() << std::endl;
std::cout << std::endl;
}
void GreenState::Initialize() {
_currState = "Green";
_interest = 5.0;
_lowerLimit = 1000.0;
_upperLimit = 100000000.0;
}
GreenState::GreenState(State* state) {
_depositor = state->GetDepositor();
_balance = state->GetBalance();
Initialize();
}
void GreenState::Deposit(const double money) {
_balance += money;
TransferNextState();
}
void GreenState::Withdraw(const double money) {
_balance -= money;
TransferNextState();
}
void GreenState::PayInterest() {
_balance = _balance * _interest;
TransferNextState();
}
void GreenState::TransferNextState() {
if (_balance < 0.0) {
_depositor->SetState(reinterpret_cast<State*>(new RedState(this)));
delete this;
return;
}
else if (_balance < _lowerLimit) {
_depositor->SetState(reinterpret_cast<State*>(new YellowState(this)));
delete this;
return;
}
else if (_balance > _upperLimit) {
std::cout << "Current depositor is too big" << std::endl;
}
}
void YellowState::Initialize() {
_currState = "Yellow";
_interest = 1.0;
_lowerLimit = 0.0;
_upperLimit = 1000.0;
}
YellowState::YellowState(State* state) {
_balance = state->GetBalance();
_depositor = state->GetDepositor();
Initialize();
}
YellowState::YellowState(const double balance, Depositor* dp) {
_balance = balance;
_depositor = dp;
Initialize();
}
void YellowState::Deposit(const double money) {
_balance += money;
TransferNextState();
}
void YellowState::Withdraw(const double money) {
_balance -= money;
TransferNextState();
}
void YellowState::PayInterest() {
_balance = _balance * _interest;
TransferNextState();
}
void YellowState::TransferNextState() {
if (_balance < _lowerLimit) {
_depositor->SetState(reinterpret_cast<State*>(new RedState(this)));
delete this;
return;
}
else if (_balance > _upperLimit) {
_depositor->SetState(reinterpret_cast<State*>(new GreenState(this)));
delete this;
return;
}
}
void RedState::Initialize() {
_currState = "Red";
_interest = 0.0;
//最多允许透支1000
_lowerLimit = -1000.0;
_upperLimit = 0.0;
//每次透支的服务费是20
_serviceFee = 20.0;
}
RedState::RedState(State* state) {
_balance = state->GetBalance();
_depositor = state->GetDepositor();
Initialize();
}
void RedState::Deposit(const double money) {
_balance += money;
TransferNextState();
}
void RedState::Withdraw(const double money) {
double newFee = money + _serviceFee;
if (_balance - newFee < _lowerLimit) {
//已到透支上限,无法执行
std::cout << "Can not withdraw due to overdraw too much" << std::endl;
} else {
_balance -= newFee;
}
}
void RedState::PayInterest() {
//not available
}
void RedState::TransferNextState() {
if (_balance > _upperLimit) {
_depositor->SetState(reinterpret_cast<State*>(new YellowState(this)));
delete this;
return;
}
}
int main() {
Depositor* dp = new Depositor("Sam");
dp->Withdraw(10.0);
dp->Withdraw(1000.0);
dp->Deposit(1500.0);
dp->Deposit(2000.0);
dp->Withdraw(5000.0);
dp->Withdraw(3000.0);
delete dp;
return 0;
}
运行结果:
Withdraw $10
Balance $-10
CurrStatus Red
Can not withdraw due to overdraw too much
Withdraw $1000
Balance $-10
CurrStatus Red
Deposited $1500
Balance $1490
CurrStatus Yellow
Deposited $2000
Balance $3490
CurrStatus Green
Withdraw $5000
Balance $-1510
CurrStatus Red
Can not withdraw due to overdraw too much
Withdraw $3000
Balance $-1510
CurrStatus Red