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+行,但是这样写出的代码过于复杂并且难以读懂,尤其是在变更需求之后,代码更加难以维护,但是状态模式解决了这些问题,状态模式把逻辑的转换放到类的结构上,这样能使逻辑变得容易理解(几乎是业务逻辑的映射),变更需求虽然需要更多的代码,但是这是值得的,因为代码虽然多但是不会复杂,逻辑不会变得混乱。