首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >状态模式解析

状态模式解析

作者头像
孟君
发布2020-05-28 22:25:01
4600
发布2020-05-28 22:25:01
举报

状态在我们的生活中无处不在。比如,听音乐的时候,我们可以选择不同的播放状态,可以是顺序播放、可以是单曲播放、也可以随机播放等;又如:线上购物后,订单从提交到完成也会有很多的状态变化,如下图所示:(当然中间可能涉及到退货等导致状态变化的,这里不展开说)。

再比如:一个TCP连接可以有Open、Acknowledge、Close等状态,一旦状态改变其行为也将发生变化。今天我们就来看一下一个状态改变后行为发生改变的模式 -- 状态模式。

一. 迭代器模式的基本介绍

意图

允许一个对象在其内部状态改变的时候改变它的行为。对象看起来似乎修改了它的类。

结构

状态模式的基本结构如下:

这里涉及到的参与者有如下几种:

  • Context(环境)
    • 定义客户感兴趣的接口。
    • 维护一个ConcreteState子类的实例,这个实例定义当前的状态。
  • State(状态)
    • 定义一个接口以封装与Context的特定状态相关的行为。
  • ConcreteState(具体子类)
    • 每个子类实现一个与Context的一个状态相关的行为。

参与者如何协作?

1、Context将与状态相关的请求委托给当前的ConreteState对象处理

2、Context可将自身作为一个参数传递给处理该请求的状态对象。这使得状态对象在必要时可访问Context。

3、Context是客户使用的主要接口。客户可用状态对象来配置一个Context,一旦一个Context配置完毕,它的客户不在需要直接与状态对象打交道。

4、Context或者ConcreteState子类都可以决定哪个状态是另外一个状态的后继者,以及是在何种条件下进行状态转换。

二. 状态模式的示例

接下来以一个2公里慢跑快跑交替训练的例子来实现一个简单的状态模式:

  • 抽象状态

package com.wangmengjun.tutorial.designpattern.state;

public abstract class State {

  abstract void handle(ExeciseContext context);

}

package com.wangmengjun.tutorial.designpattern.state;

public class FastRunningState extends State {

  @Override
  void handle(ExeciseContext context) {
    System.out.println("快跑" + context.getDistance() +"米" );
  }

}

package com.wangmengjun.tutorial.designpattern.state;

public class JoggingState extends State {

  @Override
  void handle(ExeciseContext context) {
    System.out.println("慢跑" + context.getDistance() +"米" );
  }

}

package com.wangmengjun.tutorial.designpattern.state;

public class BriskWalkingState extends State {

  @Override
  void handle(ExeciseContext context) {
    System.out.println("快走" + context.getDistance() +"米" );
  }

}
package com.wangmengjun.tutorial.designpattern.state;

public class SlowWalkingState extends State{

  @Override
  void handle(ExeciseContext context) {
    System.out.println("慢走" + context.getDistance() +"米" );

  }
}
  • 上下文环境
package com.wangmengjun.tutorial.designpattern.state;

public class ExeciseContext {

  private int distance;

  private State currentState;

  private State joggingState;

  private State fastRunState;

  private State briskWalkingState;

  private State slowWalkingState;

  public ExeciseContext() {
    joggingState = new JoggingState();
    fastRunState = new FastRunningState();
    briskWalkingState = new BriskWalkingState();
    slowWalkingState = new SlowWalkingState();

  }

  public void jogging(int distance) {
    this.setDistance(distance);
    this.setCurrentState(joggingState);
    joggingState.handle(this);
  }

  public void fastRun(int distance) {
    this.setDistance(distance);
    this.setCurrentState(fastRunState);
    fastRunState.handle(this);
  }

  public void briskWalking(int distance) {
    this.setDistance(distance);
    this.setCurrentState(briskWalkingState);
    briskWalkingState.handle(this);
  }

  public void slowWalking(int distance) {
    this.setDistance(distance);
    this.setCurrentState(slowWalkingState);
    slowWalkingState.handle(this);
  }

  /**
   * @return the distance
   */
  public int getDistance() {
    return distance;
  }

  /**
   * @param distance the distance to set
   */
  public void setDistance(int distance) {
    this.distance = distance;
  }

  /**
   * @return the currentState
   */
  public State getCurrentState() {
    return currentState;
  }

  /**
   * @param currentState the currentState to set
   */
  public void setCurrentState(State currentState) {
    this.currentState = currentState;
  }

}

简单调用一下:

package com.wangmengjun.tutorial.designpattern.state;

public class Main {

  public static void main(String[] args) {
    System.out.println("2公里慢跑 + 快跑 交替训练 - - - - - - - - - - - -开始");

    ExeciseContext context = new ExeciseContext();

    context.briskWalking(300);

    for(int i =1 ;i<=3;i++) {
      context.fastRun(100);
      context.jogging(400);
    }

    context.slowWalking(200);

    System.out.println("2公里慢跑 + 快跑 交替训练 - - - - - - - - - - - -结束");
    System.out.println("大汗淋漓,还能坚持~~");
  }
}

结果输出:

2公里慢跑 + 快跑 交替训练 - - - - - - - - - - - -开始
快走300米
快跑100米
慢跑400米
快跑100米
慢跑400米
快跑100米
慢跑400米
慢走200米
2公里慢跑 + 快跑 交替训练 - - - - - - - - - - - -结束
大汗淋漓,还能坚持~~

三. 小结

  • 状态模式使用场景

在以下情况下可以使用状态模式:

  • 一个对象的行为依赖于它所处的状态,对象的行为必须随着状态的改变而改变。
  • 对象在某个方法里依赖于一重或者多重的条件转移语句,其中有大量的代码。状态模式把条件转移语句的每一个分支都包装到一个单独的类里。这使得这些条件转移分支能够以类的方式独立存在和演化。维护这些独立的类也就不再影响到系统的其他部分。
  • 状态模式 vs. 策略模式

(1)状态模式

将一群行为封装到状态类中,主类的当前状态在状态集合中游走,随着时间的流逝,主类的行为不断变化,但这对客户端而言完全是透明的,而策略模式需要客户端明确所有策略,以指明一个具体的策略。

(2)策略模式

定义一组 算法实现,实现之间可以任意替换,而且可以在运行时动态的选择任意一种实现。 需要客户端清楚所有的策略以选择合适的策略。

如何选择?

状态模式和策略模式很相像,容易混淆,但两者意图不同。有的时候很难区分应当使用状态模式还是应当使用策略模式。一个简单的方法便是考察环境角色是否有明显的状态和状态的过渡。如果环境角色只有一个状态,那么就应当使用策略模式。而状态模式则适用于另一种情况,即环境角色有明显的状态转移

参考

[1]. 阎宏. Java与模式.电子工业出版社

[2]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 孟君的编程札记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一. 迭代器模式的基本介绍
  • 二. 状态模式的示例
  • 三. 小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档