设计模式(14) - State状态模式

目录

1.意图

2.UML类图

3.GOF角色说明

4.代码实现


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

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值