美文网首页
状态模式(State)

状态模式(State)

作者: 森码 | 来源:发表于2018-08-05 15:56 被阅读4次
  1. 定义
    允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States)。

  2. 类图


    State
  3. 例子

//没有硬币状态
public class NoQuarterState implements State{
  GumballMachine gumballMachine;
  //通过构造器得到糖果机的引用,然后将它记录在实例变量中
  public NoQuarterState(GumballMachine gumballMachine){
    this.gumballMachine=gumballMachine;
  }
  //有人投币,改变机器状态到HasQuarterState
  public void insertQuater(){
    System.out.println("You insert a quater");
    gumballMachine.setState(gumballMachine.getHasQuarterState());
  }
  //没给钱,不能要求退钱
  public void ejectQuarter(){
    System.out.println("You haven't inserted a quarter");
  }
  //没给钱,不能转手柄,要糖果
  public void turnCrank(){
    System.out.println("You turned,but there's no quarter");
  }
  //没给钱,不能发糖果
  public void dispense(){
    System.out.println("You need to pay first");
  }
}
 
//有硬币状态
public class HasQuarterState implements State{
  //增加一个随机数产生器,产生10%赢得机会
  Random randomWinner= new Random(System.currentTimeMillis());
  GumballMachine gumballMachine;
  //状态被实例化是,传入GumballMachine的引用作为参数
  public HasQuarterState(GumballMachine gumballMachine){
    this.gumballMachine=gumballMachine;
  }
  //不能连续投币两次
  public void insertQuater(){
    System.out.println("You can't insert another quater");
  }
  //退钱,并将状态转到NoQuarterState
  public void ejectQuarter(){
    System.out.println("Quarter returned");
    gumballMachine.setState(gumballMachine.getNoQuarterState());
  }
  //状态转到SoldState
  public void turnCrank(){
    System.out.println("You turned...");
    int winner=randomWinner.nextInt(10);
    if((winner==0)&&(gumballMachine.getCount()>1)){
      gumballMachine.setState(gumballMachine.getWinnerState());
    }else{
      gumballMachine.setState(gumballMachine.getSoldState());
    }
  }
  public void dispense(){
    System.out.println("No gumball dispensed");
  }
}
 
public class SoldState implements State{
  GumballMachine gumballMachine;
  //状态被实例化是,传入GumballMachine的引用作为参数
  public SoldState(GumballMachine gumballMachine){
    this.gumballMachine=gumballMachine;
  }
  //以下的动作都不合法
  public void insertQuater(){
    System.out.println("Please wait,we're already giving you a gumball");
  }
  public void ejectQuarter(){
    System.out.println("Sorry,you already turned the crank");
  }
  public void turnCrank(){
    System.out.println("Turning twice doesn't get you another gumball");
  }
  //发糖
  public void dispense(){
    gumballMachine.releaseBall();
    if(gumballMachine.getCount()>0){
      gumballMachine.setState(gumballMachine.getNoQuarterState());
    }else{
      System.out.println("Oops,out of gumball");
      gumballMachine.setState(gumballMachine.getSoldOutState());
    }
  }
}
 
public class WinnerState implements State{
  GumballMachine gumballMachine;
  //状态被实例化是,传入GumballMachine的引用作为参数
  public WinnerState(GumballMachine gumballMachine){
    this.gumballMachine=gumballMachine;
  }
  //以下的动作都不合法
  public void insertQuater(){
    System.out.println("Please wait,we're already giving you a gumball");
  }
  public void ejectQuarter(){
    System.out.println("Sorry,you already turned the crank");
  }
  public void turnCrank(){
    System.out.println("Turning twice doesn't get you another gumball");
  }
  //发糖
  public void dispense(){
    System.out.println("YOU'RE A WINNER! You get two gumballs for your quater")
    gumballMachine.releaseBall();
    if(gumballMachine.getCount()==0){
      gumballMachine.setState(gumballMachine.SoldOutState());
    }else{
      gumballMachine.releaseBall();
      if(gumballMachine.getCount()>0){
        gumballMachine.setState(gumballMachine.getNoQuarterState());
      }else{
        System.out.println("Oops,out of gumball");
        gumballMachine.setState(gumballMachine.getSoldOutState());
      }
    }
  }
}
 
//糖果售罄状态
public class SoldOutState implements State{
  GumballMachine gumballMachine;
  //状态被实例化是,传入GumballMachine的引用作为参数
  public SoldOutState(GumballMachine gumballMachine){
    this.gumballMachine=gumballMachine;
  }
  //在糖果售罄的状态下,除非重新填充糖果机,否则不做任何事
  public void insertQuater(){
    System.out.println("You can't insert a quarter,the machine is sold out");
  }
  public void ejectQuarter(){
    System.out.println("You can't eject,you haven't inserted a quarter yet");
  }
  public void turnCrank(){
    System.out.println("You turned,but there are no gumballs");
  }
  public void dispense(){
    System.out.println("No gumball dispensed");
  }
}
 
 
 
public class GumballMachine{
  State soldOutState;
  State noQuarterState;
  State hasQuarterState;
  State soldState;
  State winnerState;
  
  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);
    winnerState=new WinnerState(this);
    this.count=numberGumballs;
    //若糖果数>0,则将状态设为noQuarterState
    if(numberGumballs>0){
      state=noQuarterState;
    }
  }
  
  //设置动作,并因动作改变相应的状态
  public void insertQuarter(){
    state.insertQuarter();
  }
  public void ejectQuarter(){
    state.ejectQuarter();
  }
  /*不需要在GumballMachine中准备一个dispense()的动作方法,因为这是一个内部动作;
  用户不可以直接要求一个机器发放糖果。但可以在状态对象的turnCrank()方法中调用dispense()方法*/
  public void turnCrank(){
    state.turnCrank();
    state.dispense();
  }
  
  //允许其他对象将机器的状态转换到不同的状态
  void setState(State state){
    this.state=state;
  }
  //提供一个releaseBall()的辅助方法来释放糖果,并将count值减1
  void releaseBall(){
    System.out.println("A gumball comes rolling out the slot...");
    if(count!=0){
      count=count-1;
    }
  }
  //更新糖果机内的糖果数目,并重置机器的状态
  void refill(int count){
    this.count=count;
    state=noQuarterState;
  }
  /*其他方法,包括像getNoQuarterState()这样的用来获得每个对象的方法,
  还包括可以取得糖果数目的getCount()方法*/
}
 
//演示
public class GumballMachineTestDriver{
  public static void main(String[] args){
    GumballMachine gumballMachine= new GumballMachine(5);//糖果机装5颗糖
    
    System.out.println(gumballMachine);
    
    gumballMachine.insertQuarter();
    gumballMachine.turnCrank();
    
    System.out.println(gumballMachine);
    
    gumballMachine.insertQuarter();
    gumballMachine.turnCrank();
    gumballMachine.insertQuarter();
    gumballMachine.turnCrank();
    
    System.out.println(gumballMachine);
  }
}

代码来源于《Head First 设计模式》

补充

  • 后面会发现,状态模式 的类图和 策略模式 竟然是一样的,没有错,就是一样的,但是目的不一样,状态模式强调 一个「流程」,而策略模式则强调 解决「方案」,换句话说就是,用多个子类和用一个子类。
  • 状态模式在处理长流程的逻辑时非常有用。

相关文章

  • State模式

    状态模式(State模式) 定义 状态模式,又称状态对象模式(Pattern of Objects for S...

  • State状态模式

    状态模式的核心是将状态抽象为类,然后将状态的改变包含在类中,这样就避免了在client中写出大量的if...els...

  • 状态模式(State)

    结构 模式的组成环境类(Context): 定义客户感兴趣的接口。维护一个ConcreteState子类的实例,...

  • 状态模式(State)

    定义允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects fo...

  • 状态模式-state

    允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了他的类 state是一个接口,定义了基本操作,co...

  • 状态模式(State)

    1、概念 状态模式允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它所属的类,属于行为型模式。 2...

  • 状态模式(State)

    状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。代替大量if el...

  • 状态模式(State)

    参考博客iOS App的设计模式开发中对State状态模式的运用 使用场景: 例子1:按钮来控制一个电梯的状态,一...

  • 状态(State)模式

  • State 状态模式

    设计原则学习笔记 设计模式学习笔记 作用 将一个类在不同状态下的操作组合起来,成为一个类。方便不同状态下的操作切...

网友评论

      本文标题:状态模式(State)

      本文链接:https://www.haomeiwen.com/subject/xbybvftx.html