状态模式

本文介绍了一个基于状态模式的糖果机实现案例。通过定义State接口,实现了NoQuarterState、HasQuarterState等状态类,使得糖果机能够根据不同状态做出相应的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 定义一个State接口。在接口内,糖果机每个动作对应一个方法。
  2. 为机器中的每个状态实现状态类。这些类负责在对应的状态下进行机器的行为。
  3. 将动作委托到状态类。
    这里写图片描述
状态描述
NoQuarterState机器内有糖果,还没投入25分硬币
HasQuarterState投入25分硬币,进入SoldState
SoldState发放糖果,总数<0进入SoldOutState,否则进入NoQuarterState
SoldOutState显示”糖果售罄“

①没有投入硬币状态

class NoQuarterState : public State{
    GumballMachine * gumballMachine;
public:
    NoQuarterState(GumballMachine *gumballMachine){
        this->gumballMachine = gumballMachine;
    }
    void insertQuarter(){
        cout << "You inserted a quarter" << endl;
        gumballMachine->setState(gumballMachine->getHasQuarterState());
    }
    void ejectQuarter(){ cout<<"You haven't inserted a quarter"<<endl;}
    void tunCrank(){cout << "You turned, but there's no quarter"<<endl;}
    // 不恰当动作
    void despense(){cout << "You need to pay first"<<endl;}
};

②投入硬币状态

class HasQuarterState : public State{
    GumballMachine * gumballMachine;
public:
    HasQuarterState (GumballMachine * gumballMachine){
        this->gumballMachine = gumballMachine;
    }
    void insertQuarter(){         //  与没有投入硬币不同
        cout << "You cannot inserted another quarter" << endl;
    }
    void ejectQuarter(){ 
        cout<<"Quarter returned..."<<endl;
        gumballMachine->setState(gumballMachine->getNoQuarterState());
    }
    void tunCrank(){
        cout << "You turned"<<endl;
        gumballMachine->setState(gumballMachine->getSoldState())
    }   
    void despense(){cout << "You need to pay first"<<endl;}     // 不恰当动作
};

将每个状态局部化到自己的类中;对修改关闭,对扩展开放—-可以加入新的类。防止大块的if..else 语句出现。

糖果机:

class GumballMachine{
    State * noQuarterState;           // 状态对象
    State * hasQuarterState;
    State * soldState;
    State * soldOutState;

    State * state ;
    int count = 0;                   // 当前糖果数目为0;
public:
    GumballMachine(int numberGumballs):state(soldOutState)  {
    State * noQuarterState = new noQuarterState(this);
    State * hasQuarterState = new HasQuarterState(this);
    State * soldState = new SoldState(this);
    State * soldOutState = new soldOutState(this);  
    this->count = numberGumballs;
        if(numberGumballs > 0){
            state = noQuarterState;
        }
    }   
    void insertQuarter(){
        state->insertQuarter();
    }
    void setState(State * state){
        this->state = state;
    }
    void releaseBall(){
        cout << "A gumball comes rolling out the slot..."<<endl;
        if(count>0){count--;}
    }
    // 重新装填
    void refill(int count){
        this->count=count;
        state = noQuarterState;
    }
    // ...... getter() 如: getNoQuarterState()、getCount()
};

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。
将各种状态封装成独立的类,并将动作委托到当前状态的对象,因为行为会随着内部状态而改变。
使用组合通过简单引用不同的状态得到改变状态的假象。

在下面的两种情况下均可使用State模式:
1).一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。
2).代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

State对象可保证Context不会发生内部状态不一致的情况,因为从Context的角度看,状态转换是原子的—只需重新绑定一个变量(State对象变量).

状态转换:
这里写图片描述
这里写图片描述

这里写图片描述
将一群行为封装在状态对象中,context(对应于GumballMachine)的行为随时可以委托到那些状态对象中的一个。当前状态在状态集合中游走改变,来反应context内部状态,context的行为也会随着改变。context的客户并不会察觉。
将行为包装禁状态对象中,通过在context内简单的改变状态对象来改变context的行为。

Gumballmachine *g = new GumballMachine(5);
g->insertQuarter();
g->turnCrank();
g->insertQuarter();
g->insertQuarter();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值