HeadFrist设计模式学习之状态模式

本文通过一个糖果机实例,详细解析了状态模式的设计理念及其在解决复杂条件逻辑时的应用。通过状态模式,可以清晰地划分不同状态下的行为逻辑,使得代码结构更为简洁明了。

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

HeadFrist设计模式学习之状态模式

状态模式定义

状态模式允许对象在内部改变状态时改变它的行为,对象看起来好像修改了它的类。

状态模式用于当类由于条件语句而使逻辑变得十分复杂并且难于修改时,它将逻辑根据条件分成不同的类(每个类称之为一个状态),从而使类的内部结构变得清晰易读并且更符合业务逻辑。

需求——实现下列糖果机

class gumballMachine {
int Money = 10; // 糖果机用于找零的钱
int price = 1; // 糖果的单价
private int change=0;// 找零金额
public void soldGumball() {

}

public void toGiveChange() {

}

public void on() {

}

public void off() {

}

public void putMoneyIn(int moeny) {

}

}

上述代码是一个糖果机,具有方法:开 关 找零 放入钱 出售糖果 5 个方法,如果用普通的实现方法,
例如在soldGumball()方法中,需要判断糖果机是否开机,放入的钱是否足够,是否能够找零。。。。最糟糕的是,如果加入新的方法,比如抽取随机用户得到双倍的糖,所有的方法就都得做出修改!

加入状态模式的糖果机

首先改造糖果机:

class gumballMachine {
private int Money = 10; // 糖果机用于找零的钱
private int price = 1; // 糖果的单价
private int change = 0;//找零金额
toGiveChangeState togivechangestate;
offState offstate;
onState onstate;
State state = new onState(this);
soldGumballState soldgumballstate;

public gumballMachine() {
    // TODO Auto-generated constructor stub
    this.offstate = new offState(this);
    this.onstate = new onState(this);
    this.togivechangestate = new toGiveChangeState(this);
    this.soldgumballstate = new soldGumballState(this);
}



public void soldGumball() {
    state.soldGumball();
}

public void toGiveChange() {
    state.toGiveChange();
}

public void on() {
    state.on();
}

public void off() {
    state.off();
}

public void putMoneyIn(int money) {
    state.putMoneyIn(money);
}
//改变状态
public void toState(State state) {
    this.state = state;
}
//下面都是get/set方法
public int getChange() {
    return change;
}

public void setChange(int change) {
    this.change = change;
}

public soldGumballState getSoldgumballstate() {
    return soldgumballstate;
}

public void setSoldgumballstate(soldGumballState soldgumballstate) {
    this.soldgumballstate = soldgumballstate;
}

public int getMoney() {
    return Money;
}

public void setMoney(int money) {
    Money = money;
}

public int getPrice() {
    return price;
}

public void setPrice(int price) {
    this.price = price;
}

public toGiveChangeState getTogivechangestate() {
    return togivechangestate;
}

public void setTogivechangestate(toGiveChangeState togivechangestate) {
    this.togivechangestate = togivechangestate;
}

public offState getOffstate() {
    return offstate;
}

public void setOffstate(offState offstate) {
    this.offstate = offstate;
}

public onState getOnstate() {
    return onstate;
}
public void setOnstate(onState onstate) {
    this.onstate = onstate;
}

}

写出state接口

interface State {
public void soldGumball();
public void toGiveChange();
public void on();
public void off();
public void putMoneyIn(int money);

}

糖果机默认状态是开启,所以先看onState

class onState implements State {
private gumballMachine gm;


public onState(gumballMachine gm) {
    // TODO Auto-generated constructor stub
    this.gm=gm;
}
@Override
public void soldGumball() {
    // TODO Auto-generated method stub
    System.out.println("请先投入钱币--soldGumball");
}

@Override
public void toGiveChange() {
    // TODO Auto-generated method stub
    System.out.println("请先投入钱币--toGiveChange");
}

@Override
public void on() {
    // TODO Auto-generated method stub
    System.out.println("机器已经打开--on");
}

@Override
public void off() {
    // TODO Auto-generated method stub
    gm.toState(gm.getOffstate());
}

@Override
public void putMoneyIn(int money) {
    // TODO Auto-generated method stub
    if(money>gm.getPrice()&&(money-gm.getPrice()<=gm.getMoney()))//如果投入的钱大于单价并且可以找零,则进入找零状态
    {
        gm.setChange(money-gm.getPrice());
        gm.setMoney(gm.getMoney()+money);;
        gm.toState(gm.getTogivechangestate());//状态转换
    }
    else
        System.out.println("Money return "+money);
}

}

在onstate中,可用的方法是putMoneyIn和off,所以在这两个方法里做出了有意义的实现,其他均为提示,在putMoneyIn()方法中,用了一个if语句,这不是一个好的实现,因为状态模式就是为了消除if带来的复杂性,所以,一旦在状态模式中出现if,那么可能意味着,代码是有瑕疵的。

下面贴出剩余状态的代码

offstate

class offState implements State {

private gumballMachine gm;
public offState(gumballMachine gm) {
    // TODO Auto-generated constructor stub
    this.gm=gm;
}
@Override
public void soldGumball() {
    // TODO Auto-generated method stub
    System.out.println("机器没有打开--soldGumball");
}

@Override
public void toGiveChange() {
    // TODO Auto-generated method stub
    System.out.println("机器没有打开--toGiveChange");
}

@Override
public void on() {
    // TODO Auto-generated method stub
    gm.toState(gm.getOnstate());
}

@Override
public void off() {
    // TODO Auto-generated method stub
    System.out.println("................");
}

@Override
public void putMoneyIn(int money) {
    // TODO Auto-generated method stub
    System.out.println("机器没有打开--putMoneyIn");
}

}

toGiveChangeState

class toGiveChangeState implements State {

private gumballMachine gm;
public toGiveChangeState(gumballMachine gm) {
    // TODO Auto-generated constructor stub
    this.gm=gm;
}
@Override
public void soldGumball() {
    // TODO Auto-generated method stub

}

@Override
public void toGiveChange() {
    // TODO Auto-generated method stub
        System.out.println("GiveChange————"+gm.getChange());
         gm.setMoney(gm.getMoney()-gm.getChange());
         gm.setChange(0);
         gm.toState(gm.getSoldgumballstate());
}

@Override
public void on() {
    // TODO Auto-generated method stub
    System.out.println("机器已经开启--on");
}

@Override
public void off() {
    // TODO Auto-generated method stub
    System.out.println("操作进行中,请勿关闭--off");
}

@Override
public void putMoneyIn(int money) {
    // TODO Auto-generated method stub
    System.out.println("您已经投币--putMoneyIn");
}

}

**soldGumballState **

class soldGumballState implements State {

private gumballMachine gm;
public soldGumballState(gumballMachine gm) {
    // TODO Auto-generated constructor stub
    this.gm=gm;
}
@Override
public void soldGumball() {
    // TODO Auto-generated method stub
        System.out.println("one Gumball!!!!!!");
        gm.toState(gm.getOnstate());
}

@Override
public void toGiveChange() {
    // TODO Auto-generated method stub
    System.out.println("已经找零");
}

@Override
public void on() {
    // TODO Auto-generated method stub
    System.out.println("已开机");
}

@Override
public void off() {
    // TODO Auto-generated method stub
    System.out.println("正在操作。。。。");
}

@Override
public void putMoneyIn(int money) {
    // TODO Auto-generated method stub
    System.out.println("已经投币,谢谢");
}

}

测试代码

public static void main(String[] args) {
    // TODO Auto-generated method stub
    gumballMachine gm=new gumballMachine();
    gm.putMoneyIn(8);
    gm.toGiveChange();
    gm.soldGumball();
}

结果

GiveChange————7
one Gumball!!!!!!

在来看看应对错误操作

public static void main(String[] args) {
    // TODO Auto-generated method stub
    gumballMachine gm=new gumballMachine();
    gm.putMoneyIn(8);
    gm.putMoneyIn(8);//二次投币
    gm.off();//操作过程中关机
    gm.toGiveChange();
    gm.off();//操作过程中关机
    gm.on();//操作过程中开机
    gm.soldGumball();
    gm.off();//正常关机
    gm.putMoneyIn(8);//关机状态下投币
    }

上述代码在第一次测试的代码中加入了一些正常或错误的操作,下面看结果

您已经投币--putMoneyIn
操作进行中,请勿关闭--off
GiveChange————7
正在操作。。。。
已开机
one Gumball!!!!!!
机器没有打开--putMoneyIn

机器的运行可以看出是正常的。

如果单纯的只考虑如何实现这个糖果机的话,远远不需要这么多的代码——200+行,但是这样写出的代码过于复杂并且难以读懂,尤其是在变更需求之后,代码更加难以维护,但是状态模式解决了这些问题,状态模式把逻辑的转换放到类的结构上,这样能使逻辑变得容易理解(几乎是业务逻辑的映射),变更需求虽然需要更多的代码,但是这是值得的,因为代码虽然多但是不会复杂,逻辑不会变得混乱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值