State状态模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类

状态模式(State)适用性

1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

  这个状态通常用一个或多个枚举常量表示。

  通常,有多个操作包含这一相同的条件结构。

  State模式将每一个条件分支放入一个独立的类中。

  这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

状态模式(State)的参与者

1.Context

  定义客户感兴趣的接口。

  维护一个ConcreteState子类的实例,这个实例定义当前状态。

2.State

  定义一个接口以封装与Context的一个特定状态相关的行为。

3.ConcreteStatesubclasses

  每一子类实现一个与Context的一个状态相关的行为。

总结

状态模式的主要优点在于封装了转换规则,并枚举可能的状态,它将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为,还可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数;其缺点在于使用状态模式会增加系统类和对象的个数,且状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱,对于可以切换状态的状态模式不满足“开闭原则”的要求。

状态模式和策略模式的区别和联系(取自知乎网友的回答,很精辟):

区别:

状态模式将各个状态所对应的操作分离开来,即对于不同的状态,由不同的子类实现具体操作,不同状态的切换由子类实现,当发现传入参数不是自己这个状态所对应的参数,则自己给Context类切换状态;而策略模式是直接依赖注入到Context类的参数进行选择策略,不存在切换状态的操作练习

联系:

状态模式和策略模式都是为具有多种可能情形设计的模式,把不同的处理情形抽象为一个相同的接口,符合对扩展开放,对修改封闭的原则。还有就是,策略模式更具有一般性一些,在实践中,可以用策略模式来封装几乎任何类型的规则,只要在分析过程中听到需要在不同实践应用不同的业务规则,就可以考虑使用策略模式处理,在这点上策略模式是包含状态模式的功能的,策略模式是一个重要的设计模式。

DEMO

定义State

 //定义和Context中的状态相对应的行为
 public abstract class State{  
  public abstract void handlepush(Context c);  
  public abstract void handlepull(Context c);  
  public abstract void getcolor();  
} 

具体状态

public class BlueState extends State{  

  public void handlepush(Context c){  
        System.out.println(“变成绿色");  
     c.setState(new GreenState());  
  }  

  public void handlepull(Context c){  
       System.out.println(“变成红色");  
    c.setState(new RedState());  
  }  

  public abstract void getcolor(){  
       return (Color.blue);  
   }  
}
 
public class GreenState extends State{  

  public void handlepush(Context c){  
        System.out.println(“变成黑色");  
     c.setState(new BlackState());  
  }  

  public void handlepull(Context c){  
        System.out.println(“变成蓝色");  
     c.setState(new BlueState());  
  }  

  public abstract void getcolor(){  
        return (Color.green);  
    }  
}       

定义Context

//定义当前的状态
public class Context{  
  
  private Sate state=null; //我们将原来的 Color state 改成了新建的State state;  

  //setState是用来改变state的状态 使用setState实现状态的切换  
  pulic void setState(State state){  
    this.state=state;  
  }  

  public void push(){  
    //状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心  
    state.handlepush(this);  
    //假设sample要使用state中的一个切换结果,使用getColor()  
    Sample sample=new Sample(state.getColor());  
    sample.operate();  
  }  

  public void pull(){  
    state.handlepull(this);  
       //假设sample要使用state中的一个切换结果,使用getColor()  
    Sample2 sample2=new Sample2(state.getColor());  
    sample2.operate();  
  }  
}