设计模式入门——状态模式

背景:

糖果机有四种状态——有钱、没钱、售出糖果、糖果售完,客户有四种行为:投钱、退钱、转动曲柄、发放糖果。现在需要设计一个能够尽量有弹性而且好维护的控制器。

方案一:创建四个方法对应客户四种行为,并用if/esle语句判断糖果机的状态,以执行不同回应。

不可行:一旦多增加一个状态(如玩游戏),则需要修改全部方法,不符合“对修改关闭,对扩展打开”原则;不符合面向对象原则。

设计:

  1. 定义一个state接口,在接口内,糖果机的每个动作都有一个对应的方法;
  2. 然后为机器中的每个状态实现状态类,这些类将负责在对应的状态下进行机器的行为。
  3. 摆脱条件代码,将动作委托到状态类。

实现:

// 定义状态类接口
public interface State {
    insertQuarter();
    ejectQuarter();
    tumCrank();
    dispense();    
}

有四种状态:有钱、没钱、售出、售空   这里只列举一个状态

// 没钱的状态
public class NoQuarterState implements State {
    GumballMachine gumballMachine;

    public NoQuarterState(GumballMachine gumballMachine){
        this.gumballMachine = gumballMachine;
    }
    
    // 插入钱
    public void insertQuarter() {
        System.out.println("You inserted a quarter");
        gumballMachine.setState(gumballMachine.getHasQuarterState());
    }

    // 退钱
    public void ejectQuarter() {
        System.out.println("You haven't insert a quarter");
    }

    // 装动曲柄
    public void turnCrank() {
        System.out.println("You turnes, but there's no quarter");
    }

    // 发糖果
    public void dispense() {
        System.out.println("You need to pay first");
    }
    
}
// 糖果机
public class GumballMachine {
    State soldOutState;
    State noQuarterState;
    State hasQuarterState;
    State soldState;

    State state = soldOutState; // 默认是没有糖果的
    int count = 0;

    // 构造器,每一种状态都创建一个状态实例。
    public GumballMachine(int numberGumballs){
        soldOutState = new SoldOutState(this);
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        this.count = numberGumballs;
        if(numberGumballs > 0){
            state = noQuarterState;
        }
    }
    
    public void insertQuarter() {
        state.insertQuarter();
    } 

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

    // 发糖果只是一个动作,用户不能直接要求发糖果,需要转动曲柄
    public void turnCrank() {
        state.turnCrank();
        state.dispense();
    }

    void releaseBall() {
        System.out.println("A gumball comes rolling out the slot.");
        if(count != 0){
            count--;
        }
    }
    
}
// 主方法
public class GumballMachineDrive {
    public static void main(String[] args){
        GumballMachine gumballMachine = new GumballMachine(5);  

        gumballMachine.insertQuarter();
        gumballMachine.turnGrank();
    }
}

 

总结:

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

这个模式将状态封装成独立的类,并将动作委托到代表当前状态的对象,行为会随着内部状态的改变而改变。

策略模式和状态模式比较:

  • 状态模式:我们将一群行为封装在状态对象中,context(如本文的糖果机)的行为随时可以委托到哪些状态对象中的一个。随着时间的流逝,当前状态在状态对象集合中游走改变,以反应出context内部的状态,因此,context的行为也会跟着改变。但是context的客户对状态对象了解不多,甚至浑然不觉;
  • 策略模式:客户通常主动指定Context所要组合的策略对象是哪一个。现在固然策略模式让我们更具有弹性,能够在运行时改变策略,但对于某个context对象来说,通常都只有一个最适当的策略对象。比如鸭子被设置为不同的飞行方式。

状态模式用类代表状态,可以被多个Context实例共享。

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值