java设计模式学习之【状态模式】

引言

设想你正在使用一个在线视频播放器观看电影。随着你的互动,播放器可能处于不同的状态:播放、暂停、缓冲或结束。每个状态下,播放器的行为和可用选项都不同。这种能够根据当前状态调整行为的能力对于创建直观、响应灵敏的应用至关重要。在软件开发中,状态模式正是用来优雅地处理这种依赖状态的行为变化的情况,它帮助设计者清晰地分离和管理对象在不同状态下的行为。

状态模式简介

定义与用途

状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为。对象似乎修改了它的类。该模式封装了基于状态的行为,并且通过将每个状态实现为一个派生类的方式,将状态相关的行为局部化和集中化。

实现方式

实现状态模式通常涉及以下几个关键组件:

  • 上下文(Context):持有一个状态对象的引用,并允许外部客户端触发状态变化。
  • 状态(State):定义一个接口以封装与上下文的一个特定状态相关的行为。
  • 具体状态(Concrete States):实现状态接口的类,提供具体的行为实现。

使用场景

状态模式适用于以下场景:

  • 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。
  • 当一个操作中含有庞大的多分支结构,并且这些分支依赖于对象的状态时。

例如:

  1. 文档审批流程:文档在创建、审批、发布等不同状态之间转换,每个状态下文档的行为(如编辑、审批、发布)不同。
  2. 交通信号灯:信号灯根据时间或条件变化其状态(红灯、绿灯、黄灯),每种状态下的行为(比如停车、行驶)也不同。
  3. 游戏中的角色状态:游戏角色可能有多种状态(正常、加速、减速、无敌等),每种状态下角色的行为和属性有所不同。

优势与劣势

  • 优势
    • 封装了基于状态的行为,并且将状态相关的行为局部化。
    • 通过消除庞大的条件分支语句,使得状态转换显式化。
  • 劣势
    • 如果状态多且复杂,会导致有很多状态类,增加系统复杂度。
    • 应用不当会导致状态和策略模式混淆。

在Spring框架中的应用

在Spring框架中,状态模式可能不会像某些其他模式那样直接被提及,但是其核心概念在某些Spring的功能和管理方式中得到了体现。以下是在Spring框架中体现状态模式概念的几个方面:

1. Spring状态机(Spring State Machine)
Spring状态机(Spring State Machine)是对状态模式概念的直接实现。它提供了一个强大的方式来管理状态转换以及状态下的行为。在复杂逻辑和工作流的情况下,如订单管理、配置管理等,Spring状态机可以帮助开发者以声明性的方式管理状态和事件。

2. Spring Web Flow
在Spring Web Flow中,状态模式的概念被用于管理Web应用中的页面流。页面流可以看作是一系列状态和发生在这些状态之间的事件。Spring Web Flow允许开发者定义页面流程的状态(如视图状态、决策状态等),并且基于发生的事件移动到不同的状态,从而提供丰富的用户界面导航。

3. Spring Security的认证状态
在Spring Security中,用户的认证状态(如已认证、未认证、认证失败等)可以被看作是用户在安全上下文中的状态。Spring Security使用一系列的过滤器和认证管理器来处理这些状态变化,并执行相应的安全逻辑。

4. Session和会话管理
在Spring MVC中,会话(Session)的状态管理也可以被看作是状态模式的一个例子。会话中的数据代表了用户的状态(如用户认证、选择的语言、配置偏好等),这些状态可能会随着用户的交互而改变。

状态示例

在这里插入图片描述
步骤 1:创建接口

public interface State {
   public void doAction(Context context);
}

State 接口定义了一个 doAction 方法,所有的具体状态类将实现这个接口,以提供相应的行为。

步骤 2:创建实现相同接口的具体类

public class StartState implements State {

   public void doAction(Context context) {
      System.out.println("播放器处于开始状态");
      context.setState(this);    
   }

   public String toString(){
      return "开始状态";
   }
}

StartState 是一个具体的状态类,表示开始状态。当播放器处于这个状态时,它将执行相应的操作并更新上下文状态。

public class StopState  implements State{

    @Override
    public void doAction(Context context) {
        System.out.println("播放器处于停止状态");
        context.setState(this);
    }

    @Override
    public String toString(){
        return "停止状态";
    }

}

StopState 是另一个具体的状态类,表示停止状态。在这个状态下,它将执行停止状态下的操作并更新上下文状态。

步骤 3:创建上下文类

public class Context {
   private State state;

   public Context(){
      state = null;
   }

   public void setState(State state){
      this.state = state;        
   }

   public State getState(){
      return state;
   }
}

Context 类持有一个状态对象的引用,并允许客户端通过 setState 方法改变其状态。它的行为随着状态的改变而改变。

步骤 4:使用上下文来看到状态改变时的行为变化

public class StatePatternDemo {
   public static void main(String[] args) {
      Context context = new Context();

      StartState startState = new StartState();
      startState.doAction(context);

      System.out.println("当前状态: " + context.getState().toString());

      StopState stopState = new StopState();
      stopState.doAction(context);

      System.out.println("当前状态: " + context.getState().toString());
   }
}

在这里插入图片描述

在这个演示类中,我们创建了一个上下文对象并改变其状态。首先,我们将上下文设置为开始状态并执行相关操作,然后我们将上下文设置为停止状态并执行相关操作。在每个状态改变后,我们都打印出当前的状态来看到行为的变化。

这个示例演示了状态模式如何使对象的行为随其状态的改变而改变。通过将每个状态的行为封装在单独的类中,我们可以很容易地增加新的状态和行为,同时保持不同状态的行为分离和独立。

代码地址

23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
状态模式是一种行为型设计模式,它允许对象在其内部状态发生改变时改变它的行为。 状态模式的核心思想是将对象的状态从对象本身中分离出来,并将状态的行为委托给代表该状态的对象。这样,当对象的状态发生改变时,它将委托给代表该状态的对象来处理行为,而不是在对象本身中进行判断和处理。 状态模式包含以下几个角色: 1. Context(上下文):定义客户端感兴趣的接口,并维护一个当前状态的引用。 2. State(状态):定义状态的接口,并封装与该状态相关的行为。 3. ConcreteState(具体状态):实现状态的接口,并封装与该状态相关的行为。 下面以一个简单的电梯状态转换为例来说明状态模式: ```java // Context public class Elevator { private State state; public Elevator() { this.state = new ClosedState(); } public void setState(State state) { this.state = state; } public void open() { state.open(this); } public void close() { state.close(this); } public void run() { state.run(this); } public void stop() { state.stop(this); } } // State public interface State { void open(Elevator elevator); void close(Elevator elevator); void run(Elevator elevator); void stop(Elevator elevator); } // ConcreteState public class ClosedState implements State { @Override public void open(Elevator elevator) { System.out.println("电梯门打开"); elevator.setState(new OpenedState()); } @Override public void close(Elevator elevator) { System.out.println("电梯门已关闭"); } @Override public void run(Elevator elevator) { System.out.println("电梯开始运行"); elevator.setState(new RunningState()); } @Override public void stop(Elevator elevator) { System.out.println("电梯已停止"); } } public class OpenedState implements State { @Override public void open(Elevator elevator) { System.out.println("电梯门已打开"); } @Override public void close(Elevator elevator) { System.out.println("电梯门关闭"); elevator.setState(new ClosedState()); } @Override public void run(Elevator elevator) { System.out.println("电梯门未关闭,无法运行"); } @Override public void stop(Elevator elevator) { System.out.println("电梯已停止"); elevator.setState(new StoppedState()); } } public class RunningState implements State { @Override public void open(Elevator elevator) { System.out.println("电梯运行中,无法开门"); } @Override public void close(Elevator elevator) { System.out.println("电梯运行中,无法关门"); } @Override public void run(Elevator elevator) { System.out.println("电梯仍在运行中"); } @Override public void stop(Elevator elevator) { System.out.println("电梯已停止"); elevator.setState(new StoppedState()); } } public class StoppedState implements State { @Override public void open(Elevator elevator) { System.out.println("电梯门打开"); elevator.setState(new OpenedState()); } @Override public void close(Elevator elevator) { System.out.println("电梯门已关闭"); elevator.setState(new ClosedState()); } @Override public void run(Elevator elevator) { System.out.println("电梯开始运行"); elevator.setState(new RunningState()); } @Override public void stop(Elevator elevator) { System.out.println("电梯已停止"); } } ``` 在上面的例子中,电梯的状态可以是“开门状态”、“关门状态”、“运行状态”和“停止状态”,而这些状态的行为可以通过状态模式来进行封装和处理。具体来说,电梯的状态被封装为一个状态接口,并有不同的状态实现类来实现具体的行为。在上下文类中,我们维护了一个当前状态的引用,并将操作委托给当前状态的对象来处理。 当电梯的状态发生改变时,我们只需要更改当前状态的引用即可,而不需要在上下文类中进行状态判断和处理,从而使得代码更加清晰、简洁、可维护性更高。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值