【状态模式】

50 阅读3分钟

定义

状态模式(State Pattern)是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为。这个对象看起来好像修改了它的类。

以下是状态模式的主要特点和定义:

主要角色

  1. Context(环境类)

    • 定义客户端所感兴趣的接口,并且保留一个具体状态类的实例,这个实例来决定当前的状态。
    • 负责处理请求,将请求委托给当前的状态对象来处理。
  2. State(抽象状态类)

    • 定义一个接口以封装与 Context 的一个特定状态相关的行为。
  3. ConcreteState(具体状态类)

    • 每一个具体状态类都实现了抽象状态类定义的接口,负责具体的状态相关行为。

业务

假设我们正在开发一个游戏角色,这个角色有不同的状态,如正常状态、加速状态和受伤状态。每个状态下角色的行为都不同。

classDiagram
    class CharacterState {
        +move() : void
        +attack() : void
    }
    class NormalState {
        +move() : void
        +attack() : void
    }
    class AcceleratedState {
        +move() : void
        +attack() : void
    }
    class InjuredState {
        +move() : void
        +attack() : void
    }
    class GameCharacter {
        -CharacterState state
        +GameCharacter()
        +setState(CharacterState) : void
        +move() : void
        +attack() : void
    }
    CharacterState <|-- NormalState
    CharacterState <|-- AcceleratedState
    CharacterState <|-- InjuredState
    GameCharacter "1" --> "1" CharacterState

一、定义抽象状态类(State)

interface CharacterState {
    void move();
    void attack();
}

二、定义具体状态类(ConcreteState)

  1. 正常状态:
class NormalState implements CharacterState {
    @Override
    public void move() {
        System.out.println("Moving at normal speed.");
    }

    @Override
    public void attack() {
        System.out.println("Normal attack.");
    }
}
  1. 加速状态:
class AcceleratedState implements CharacterState {
    @Override
    public void move() {
        System.out.println("Moving at accelerated speed.");
    }

    @Override
    public void attack() {
        System.out.println("Powerful attack.");
    }
}
  1. 受伤状态:
class InjuredState implements CharacterState {
    @Override
    public void move() {
        System.out.println("Moving slowly.");
    }

    @Override
    public void attack() {
        System.out.println("Weak attack.");
    }
}

三、定义环境类(Context)

class GameCharacter {
    private CharacterState state;

    public GameCharacter() {
        state = new NormalState();
    }

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

    public void move() {
        state.move();
    }

    public void attack() {
        state.attack();
    }
}

四、使用状态模式

public class StatePatternExample {
    public static void main(String[] args) {
        GameCharacter character = new GameCharacter();

        character.move();
        character.attack();

        character.setState(new AcceleratedState());
        character.move();
        character.attack();

        character.setState(new InjuredState());
        character.move();
        character.attack();
    }
}

在这个例子中,CharacterState是抽象状态类,定义了角色的行为接口。NormalStateAcceleratedStateInjuredState是具体状态类,实现了不同状态下的具体行为。GameCharacter是环境类,它持有一个当前状态对象,并将行为委托给当前状态对象来执行。通过这种方式,我们可以在运行时根据角色的状态改变其行为,实现了状态模式的设计。

总结

使用场景

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

    • 例如,一个订单在不同的状态(如待支付、已支付、已发货、已完成等)下有不同的操作和显示。
  2. 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。

    • 使用状态模式可以将这些条件语句转换为状态类,使得代码更加清晰和易于维护。

优点

  1. 状态模式将与特定状态相关的行为局部化,使得代码更加清晰、易于理解和维护。

    • 每个状态类只负责处理自己的状态相关的行为,而不是将所有的状态相关行为都集中在一个庞大的类中。
  2. 状态转换更加清晰。

    • 通过状态类之间的切换,可以清晰地看到对象在不同状态之间的转换过程。
  3. 易于扩展。

    • 可以方便地添加新的状态类,而不会影响现有的状态类和环境类。

缺点

  1. 状态模式会增加系统中类和对象的数量。

    • 对于每个状态都需要创建一个具体状态类,这可能会导致系统变得复杂。
  2. 状态模式的结构相对复杂,对于简单的状态管理可能会引入不必要的复杂性。