Java设计模式--状态模式(State)

概述


  • 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使用状态模式。
  • 状态模式将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象状态可以灵活变化,对于客户端而言,无须关心对象状态的转换以及对象所处的当前状态,无论对于何种状态的对象,客户端都可以一致处理。
  • 别名为状态对象(Objects for States)
  • 状态模式是一种对象行为型模式。
  • 学习难度:★★★☆☆
  • 使用频率:★★★☆☆

概述优缺点


  • 优点
    • 避免if…else
    • 每个状态封装成类,符合单一职责
  • 缺点
    • 状态类膨胀

类图


在这里插入图片描述

组成角色


  • 环境角色(Context)
  • 状态角色(State)
  • 具体状态角色(ConcreteState)

Code Example


环境角色(Context)
/**
 * 使用环境(Context)角色:客户程序是通过它来满足自己的需求。它定义了客户程序需要的接口;并且维护一个具体状态角色的实例,这个实例来决定当前的状态。
 * 由自身的状态决定自身的行为。
 * 
 * @author yanbin
 * 
 */
public class Context {

   // 状态
   private State state;

   // 带有初始状态的构造器
   public Context(State state) {
      this.state = state;
   }

   // 设置初始状态
   public void setState(State state) {
      this.state = state;
   }

   // 下一步
   public void nextStep() {
      if (this.state != null) {
         this.state.nextStep(this);
      }
   }

   // 上一步
   public void lastStep() {
      if (this.state != null) {
         this.state.lastStep(this);
      }
   }

   // 返回当前状态
   public State getState() {
      return this.state;
   }

}
状态角色(State)
/**
 * 状态(State)角色:定义一个接口以封装与使用环境角色的一个特定状态相关的行为。
 * 
 * @author yanbin
 * 
 */
public interface State {

   // 执行'上一步' 操作
   public void lastStep(Context ctx);

   // 执行'下一步' 操作
   public void nextStep(Context ctx);

}
具体状态角色(ConcreteState)
/**
 * 具体状态(Concrete State)角色:实现状态角色定义的接口。
 * 
 * @author yanbin
 * 
 */
public class FirstState implements State {

   // first->null
   public void lastStep(Context ctx) {
      ctx.setState(null);
   }

   // first->second
   public void nextStep(Context ctx) {
      ctx.setState(new SecondState());
   }

   @Override
   public String toString() {
      return "First State";
   }
   
}
/**
 * 具体状态(Concrete State)角色:实现状态角色定义的接口。
 * 
 * @author yanbin
 * 
 */
public class SecondState implements State {

   // second->first
   public void lastStep(Context ctx) {
      ctx.setState(new FirstState());
   }

   // second->third
   public void nextStep(Context ctx) {
      ctx.setState(new ThirdState());
   }

   @Override
   public String toString() {
      return "Second State";
   }

}
/**
 * 具体状态(Concrete State)角色:实现状态角色定义的接口。
 * 
 * @author yanbin
 * 
 */
public class ThirdState implements State {

   // third->second
   public void lastStep(Context ctx) {
      ctx.setState(new SecondState());
   }

   // third->null
   public void nextStep(Context ctx) {
      ctx.setState(null);
   }

   @Override
   public String toString() {
      return "Third State";
   }

}
客户端
/**
 * 状态模式:允许一个对象在其内部状态改变时改变它 的行为。状态模式可以有效的替换充满在程序中的 if else
 * 语句:将不同条件下的行为封装在一个类里面,再给这些类一个统一的父类来约束他们。<br>
 * 组成:使用环境(Context)角色;状态(State)角色;具体状态(Concrete State)角色。<br>
 * 使用场景:一个对象的行为取决于它的状态, 并且它必须在运行时刻根据状态改变它的行为。一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。
 * 状态模式和策略模式的区别:区分这两个模式的关键是看行为是 由状态驱动还是由一组算法驱动;策略模式用来处理算法变化,而状态模式则是处理状态变化。
 * 策略模式中,算法是否变化完全是由客户程序来决定的,而且往往一次只能选择一种算 法,不存在算法中途发生变化的情况。
 * 而状态模式如定义中所言,在它的生命周期中存在着状态的转变和行为得更改,而且状 态变化是一个线形的整体;对于客户程序来言,这种状态变化往往是透明的。
 * 
 * @author yanbin
 * 
 */
public class StatePattern {

   public static void main(String[] args) {
      // 顺行起点first
      State state = new FirstState();
      Context ctx = new Context(state);

      for (int i = 0; i < 6; i++) {
         state = ctx.getState();
         System.out.print(state);
         if (state == null) {
            break;
         }
         System.out.print("->");
         // 顺流
         ctx.nextStep();
      }
      System.out.println("");    

      // 逆行起点third
      state = new ThirdState();
      ctx = new Context(state);
      for (int i = 0; i < 6; i++) {
         state = ctx.getState();

         System.out.print(state);
         if (state == null) {
            break;
         }
         System.out.print("->");
         // 逆流
         ctx.lastStep();
      }
   }

}

猜你喜欢

转载自blog.csdn.net/yanbin0830/article/details/89319722
今日推荐