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

一、状态模式概述

1.1 什么是状态模式

Java中的状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。这种模式主要用于实现对象之间的解耦,使得对象可以在不修改其结构的情况下改变其行为。

Java中的状态模式通常包括以下角色:

上下文(Context):负责维护当前状态和根据当前状态调用相应的状态处理方法。
状态(State):表示对象的状态,每个状态都有一个对应的处理方法。
具体状态(Concrete State):是状态的具体实现,继承自状态接口。

1.2 简单实现状态模式

// 状态接口
interface State {
    void handle(Context context);
}

// 具体状态A
class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        System.out.println("当前状态为A");
        context.setState(this);
    }
}

// 具体状态B
class ConcreteStateB implements State {
    @Override
    public void handle(Context context) {
        System.out.println("当前状态为B");
        context.setState(this);
    }
}

// 上下文类
class Context {
    private State state;

    public Context() {
        this.state = new ConcreteStateA(); // 初始状态为A
    }

    public void request() {
        state.handle(this); // 根据当前状态执行相应操作
    }

    public void setState(State state) {
        this.state = state; // 切换状态
    }
}

public class Main {
    public static void main(String[] args) {
        Context context = new Context(); // 创建上下文对象
        context.request(); // 输出:当前状态为A,并切换到状态A
        context.request(); // 输出:当前状态为B,并切换到状态B
    }
}

1.3 使用状态模式的注意事项

  • 1、状态模式适用于当一个对象在它的状态发生改变时,它的行为也随着发生较大的变化。也就是说,在行为受状态约束的情况下可以使用状态模式。如果一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求不同行为的时候,可以考虑使用状态模式。

  • 2、状态模式的关键点在于不同的状态下对于同一行为有不同的响应。这其实就是一个将 if~else 用多态来实现的一个具体示例。

  • 3、状态模式的使用必然会增加系统类和对象的个数。尽管状态模式提供了一个更好的方法来组织与特定状态相关的代码,将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性与可维护性,但会增加系统的复杂性。

  • 4、当使用状态模式时,需要避免过多的状态转换,如果对象的状态太多,可能会导致系统变得复杂难以维护。最好保证对象的状态不超过5个。

  • 5、Context类应当尽可能地简单,它的职责主要是负责维护当前状态,并根据当前状态调用相应的状态处理方法。如果Context类过于复杂,可能会影响系统的可维护性和可扩展性。

二、状态模式的用途

  • 1、当一个对象的状态改变时,它的行为也随着发生较大的变化。也就是说,在行为受状态约束的情况下可以使用状态模式。如果一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求不同行为的时候,可以考虑使用状态模式。

  • 2、状态模式的关键点在于不同的状态下对于同一行为有不同的响应。这其实就是一个将 if~else 用多态来实现的一个具体示例。

  • 3、状态模式提供了一个更好的方法来组织与特定状态相关的代码,将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性与可维护性。

  • 4、当使用状态模式时,需要避免过多的状态转换,如果对象的状态太多,可能会导致系统变得复杂难以维护。最好保证对象的状态不超过5个。

三、状态模式实现方式

3.1 使用枚举类型实现状态模式

首先,定义一个表示状态的枚举类型:

public enum State {
    STATE_A,
    STATE_B,
    STATE_C
}

然后,创建一个类,该类包含一个表示当前状态的变量,并提供一个方法来更改状态:

public class StatePatternDemo {
    private State currentState;

    public StatePatternDemo() {
        currentState = State.STATE_A;
    }

    public void changeState(State newState) {
        currentState = newState;
        performAction();
    }

    private void performAction() {
        switch (currentState) {
            case STATE_A:
                System.out.println("执行状态 A 的操作");
                break;
            case STATE_B:
                System.out.println("执行状态 B 的操作");
                break;
            case STATE_C:
                System.out.println("执行状态 C 的操作");
                break;
        }
    }
}

最后,创建一个主类来测试状态模式:

public class Main {
    public static void main(String[] args) {
        StatePatternDemo demo = new StatePatternDemo();
        demo.changeState(State.STATE_B);
        demo.changeState(State.STATE_C);
    }
}

运行上述代码,将输出以下结果:

执行状态 A 的操作
执行状态 B 的操作
执行状态 C 的操作

3.2 使用内部类实现状态模式

首先,创建一个外部类 Context,它将包含一个表示当前状态的内部类 State 的实例变量。然后,为每个可能的状态创建一个内部类,这些类将实现一个共同的接口,该接口定义了所有状态都需要实现的方法。最后,在 Context 类中,提供一个方法来更改状态,并调用新状态的相应方法。

public class Context {
    // 内部类 State,表示状态
    private State state;

    public Context(State state) {
        this.state = state;
    }

    // 更改状态的方法
    public void setState(State state) {
        this.state = state;
    }

    // 执行状态操作的方法
    public void request() {
        state.handle();
    }
}

// 定义一个接口,表示状态需要实现的方法
interface State {
    void handle();
}

// 具体状态类 A
class StateA implements State {
    @Override
    public void handle() {
        System.out.println("处理状态 A");
    }
}

// 具体状态类 B
class StateB implements State {
    @Override
    public void handle() {
        System.out.println("处理状态 B");
    }
}

// 具体状态类 C
class StateC implements State {
    @Override
    public void handle() {
        System.out.println("处理状态 C");
    }
}

// 测试代码
public class Main {
    public static void main(String[] args) {
        Context context = new Context(new StateA());
        context.request(); // 输出:处理状态 A

        context.setState(new StateB());
        context.request(); // 输出:处理状态 B

        context.setState(new StateC());
        context.request(); // 输出:处理状态 C
    }
}

在这个示例中,我们创建了一个名为 Context 的外部类,它包含一个名为 State 的内部类实例变量。我们还为每个可能的状态创建了一个内部类(StateA、StateB 和 StateC),它们都实现了一个名为 State 的接口。在 Context 类中,我们提供了一个名为 setState 的方法来更改状态,并调用新状态的 handle 方法。

3.3 使用接口实现状态模式

首先,创建一个表示状态的接口:

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

然后,创建具体的状态类,实现State接口:

public class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        System.out.println("当前状态是A");
        context.setState(new ConcreteStateB());
    }
}

public class ConcreteStateB implements State {
    @Override
    public void handle(Context context) {
        System.out.println("当前状态是B");
        context.setState(new ConcreteStateA());
    }
}

接下来,创建一个上下文类,用于存储当前状态,并实现State接口:

public class Context {
    private State state;

    public Context() {
        state = new ConcreteStateA();
    }

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

    public void request() {
        state.handle(this);
    }
}

最后,在主函数中测试状态模式:

public class StatePatternDemo {
    public static void main(String[] args) {
        Context context = new Context();
        context.request(); // 输出:当前状态是A
        context.request(); // 输出:当前状态是B
        context.request(); // 输出:当前状态是A
    }
}

在这个示例中,我们定义了一个State接口,以及两个具体的状态类ConcreteStateA和ConcreteStateB。Context类负责存储当前状态,并在需要时切换状态。通过调用Context类的request方法,我们可以在不同状态之间进行切换。

3.4 使用抽象类实现状态模式

首先,创建一个表示状态的抽象类State:

public abstract class State {
    public abstract void handle(Context context);
}

然后,创建具体的状态类,例如StartState和StopState:

public class StartState extends State {
    @Override
    public void handle(Context context) {
        System.out.println("启动状态");
        context.setState(new StopState());
    }
}

public class StopState extends State {
    @Override
    public void handle(Context context) {
        System.out.println("停止状态");
        context.setState(new StartState());
    }
}

接下来,创建一个表示上下文的类Context,并包含一个State类型的成员变量:

public class Context {
    private State state;

    public Context() {
        this.state = new StartState();
    }

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

    public void request() {
        state.handle(this);
    }
}

最后,在主函数中测试状态模式:

public class Main {
    public static void main(String[] args) {
        Context context = new Context();
        context.request(); // 输出:启动状态
        context.request(); // 输出:停止状态
        context.request(); // 输出:启动状态
    }
}

在这个示例中,我们使用抽象类State定义了状态的接口,并创建了两个具体的状态类StartState和StopState。Context类负责管理当前状态,并在需要时切换状态。通过调用context.request()方法,我们可以在不同状态之间进行切换。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java设计模式是一组经过实践验证的面向对象设计原则和模式,可以帮助开发人员解决常见的软件设计问题。下面是常见的23种设计模式: 1. 创建型模式(Creational Patterns): - 工厂方法模式(Factory Method Pattern) - 抽象工厂模式(Abstract Factory Pattern) - 单例模式(Singleton Pattern) - 原型模式(Prototype Pattern) - 建造者模式(Builder Pattern) 2. 结构型模式(Structural Patterns): - 适配器模式(Adapter Pattern) - 桥接模式(Bridge Pattern) - 组合模式(Composite Pattern) - 装饰器模式(Decorator Pattern) - 外观模式(Facade Pattern) - 享元模式(Flyweight Pattern) - 代理模式(Proxy Pattern) 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility Pattern) - 命令模式(Command Pattern) - 解释器模式(Interpreter Pattern) - 迭代器模式(Iterator Pattern) - 中介者模式(Mediator Pattern) - 备忘录模式(Memento Pattern) - 观察者模式(Observer Pattern) - 状态模式State Pattern) - 策略模式(Strategy Pattern) - 模板方法模式(Template Method Pattern) - 访问者模式(Visitor Pattern) 4. 并发型模式(Concurrency Patterns): - 保护性暂停模式(Guarded Suspension Pattern) - 生产者-消费者模式(Producer-Consumer Pattern) - 读写锁模式(Read-Write Lock Pattern) - 信号量模式(Semaphore Pattern) - 线程池模式(Thread Pool Pattern) 这些设计模式可以根据问题的特点和需求来选择使用,它们提供了一些可复用的解决方案,有助于开发高质量、可维护且易于扩展的软件系统。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一碗油泼面

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值