状态模式原理剖析

news/2024/9/28 19:37:05 标签: 状态模式, ui, ajax, java, 设计模式

状态模式原理剖析》

状态模式(State Pattern) 是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。换句话说,当对象状态发生变化时,它的行为也会随之变化。
通过状态模式,可以消除通过 if-else 或 switch-case 来判断状态的需要。每个状态的行为封装在独立的类中

核心思想

状态模式将对象的不同状态封装成独立的类,并让对象在不同的状态下有不同的行为。状态模式通过将状态的行为和逻辑封装在状态类中,使得状态之间的转换变得清晰、易扩展。

UML 类图:状态模式

在这里插入图片描述

角色说明

  1. Context(上下文类)
    • 持有一个 State 对象,表示当前的状态。
    • 负责将状态的转换委托给具体的状态类。
  2. State(抽象状态类)
    • 定义了一个 handle() 方法,用于处理当前状态的逻辑。
  3. ConcreteState(具体状态类)
    • 实现 State 接口,负责在具体状态下的行为。
    • 不同的具体状态类表示对象在不同状态下的不同行为。

案例:订单状态管理

场景描述:

在电商平台或者订餐系统中,订单的状态是一个典型的使用状态模式的场景。订单的状态通常包括以下几种:

  • 新订单NewOrder):订单刚创建。
  • 已付款Paid):订单已付款,等待发货。
  • 已发货Shipped):订单已经发货,等待确认收货。
  • 已完成Completed):订单交易完成。
  • 取消订单Cancelled):订单被取消。

每个订单的状态都会影响订单的行为。例如,只有在新订单状态下,用户才可以取消订单;在已付款状态下,用户不能取消订单,但可以查询发货状态;而在已完成取消状态下,订单是不可修改的。

状态模式处理的好处:

  1. 避免复杂的 if-else 条件判断:不同状态下的订单行为各不相同,使用状态模式可以避免在代码中出现大量的 if-else 条件判断(如:if(order.status == "paid") { ... } else if(order.status == "shipped") { ... })。
  2. 状态行为封装:将每种状态的行为封装到相应的状态类中,使得状态切换清晰,便于维护和扩展。
  3. 提高扩展性:当需要新增或修改订单状态时,可以通过新增状态类而不影响现有代码逻辑,符合开闭原则。

代码实现:订单状态管理

Step 1: 定义状态接口

我们首先定义一个 OrderState 接口,声明了订单状态下的所有可能的行为,比如支付、发货、取消和完成

java">// 状态接口:订单状态
public interface OrderState {
    void pay(OrderContext context);
    void ship(OrderContext context);
    void cancel(OrderContext context);
    void complete(OrderContext context);
}

Step 2: 实现具体的状态类

新订单状态(NewOrderState)

当订单处于新订单状态时,可以进行支付或取消操作,但不能发货或完成。

java">// 具体状态类:新订单状态
public class NewOrderState implements OrderState {

    @Override
    public void pay(OrderContext context) {
        System.out.println("Order paid. Moving to Paid state.");
        context.setState(new PaidOrderState());
    }

    @Override
    public void ship(OrderContext context) {
        System.out.println("Cannot ship order. Order is not paid yet.");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("Order cancelled.");
        context.setState(new CancelledOrderState());
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("Cannot complete order. Order is not paid yet.");
    }
}

已付款状态(PaidOrderState)

当订单处于已付款状态时,可以发货,但不能取消订单。

java">// 具体状态类:已付款状态
public class PaidOrderState implements OrderState {

    @Override
    public void pay(OrderContext context) {
        System.out.println("Order is already paid.");
    }

    @Override
    public void ship(OrderContext context) {
        System.out.println("Order shipped. Moving to Shipped state.");
        context.setState(new ShippedOrderState());
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("Cannot cancel. Order is already paid.");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("Cannot complete order. Order is not shipped yet.");
    }
}

已发货状态(ShippedOrderState)

当订单处于已发货状态时,可以完成订单,但不能再发货或取消订单。

java">// 具体状态类:已发货状态
public class ShippedOrderState implements OrderState {

    @Override
    public void pay(OrderContext context) {
        System.out.println("Order is already paid and shipped.");
    }

    @Override
    public void ship(OrderContext context) {
        System.out.println("Order is already shipped.");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("Cannot cancel. Order is already shipped.");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("Order completed. Moving to Completed state.");
        context.setState(new CompletedOrderState());
    }
}

已完成状态(CompletedOrderState)

订单已经完成后,所有操作都无法再进行。

java">// 具体状态类:已完成状态
public class CompletedOrderState implements OrderState {

    @Override
    public void pay(OrderContext context) {
        System.out.println("Cannot pay. Order is already completed.");
    }

    @Override
    public void ship(OrderContext context) {
        System.out.println("Cannot ship. Order is already completed.");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("Cannot cancel. Order is already completed.");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("Order is already completed.");
    }
}

取消订单状态(CancelledOrderState)

订单被取消后,所有操作都无法再进行。

java">// 具体状态类:取消订单状态
public class CancelledOrderState implements OrderState {

    @Override
    public void pay(OrderContext context) {
        System.out.println("Cannot pay. Order is cancelled.");
    }

    @Override
    public void ship(OrderContext context) {
        System.out.println("Cannot ship. Order is cancelled.");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("Order is already cancelled.");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("Cannot complete. Order is cancelled.");
    }
}

Step 3: 创建上下文类

OrderContext 持有订单的当前状态,并且通过调用当前状态的行为方法来执行操作。

java">// 上下文类:订单上下文
public class OrderContext {
    private OrderState currentState;

    public OrderContext() {
        this.currentState = new NewOrderState(); // 初始状态为新订单
    }

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

    public void pay() {
        currentState.pay(this);
    }

    public void ship() {
        currentState.ship(this);
    }

    public void cancel() {
        currentState.cancel(this);
    }

    public void complete() {
        currentState.complete(this);
    }
}

Step 4: 测试状态模式

java">public class OrderStatePatternDemo {

    public static void main(String[] args) {
        OrderContext order = new OrderContext();

        // 订单状态:新订单
        order.pay();       // 支付订单
        order.ship();      // 发货订单
        order.complete();  // 完成订单

        // 尝试取消已完成订单
        order.cancel();    // 无法取消已完成订单
    }
}

输出结果

java">Order paid. Moving to Paid state.
Order shipped. Moving to Shipped state.
Order completed. Moving to Completed state.
Cannot cancel. Order is already completed.

状态模式解决的问题

  1. 避免条件判断的复杂性
    • 如果不使用状态模式,代码中会充满大量的 if-elseswitch-case 条件判断。状态模式将这些判断逻辑分散到各个状态类中,避免了复杂的条件分支。
  2. 清晰的状态转换逻辑
    • 状态模式将状态和行为封装在状态类中,所有的状态转换逻辑都非常清晰。状态的变化和行为的变化是分开的,彼此不干扰。
  3. 遵循开闭原则
    • 新的状态和行为可以通过增加新的状态类实现,而不需要修改已有的状态逻辑,符合开闭原则,便于扩展。

总结

状态模式 是一种强大的设计模式,尤其适合在对象状态频繁变化行为因状态不同而变化的场景中。在订单状态管理的案例中,状态模式帮助我们将订单在不同状态下的行为封装起来,使得代码更加灵活、清晰,同时提高了代码的可扩展性。

通过状态模式,开发者可以轻松应对复杂的状态转换逻辑,并在不修改已有代码的前提下添加新的状态,保证系统的灵活性和扩展性。

优点

  1. 遵循开闭原则
    • 新增状态类时,不需要修改现有的上下文类或状态类,可以轻松扩展系统的状态和行为。
  2. 清晰的状态转换
    • 将状态转换的逻辑封装在各自的状态类中,使得状态之间的切换更加清晰且易于维护。
  3. 消除复杂的条件判断
    • 通过状态模式,消除了通过 if-elseswitch-case 来判断状态的需要。每个状态的行为封装在独立的类中。

缺点

  1. 类的数量增加
    • 每种状态都有一个对应的类,可能导致类的数量急剧增加,增加系统的复杂性。
  2. 状态切换逻辑可能复杂
    • 如果系统中状态过多,且状态间的转换规则复杂,可能会增加状态管理的难度。

http://www.niftyadmin.cn/n/5681723.html

相关文章

数据结构:队列及其应用

队列(Queue)是一种特殊的线性表,它的主要特点是先进先出(First In First Out,FIFO)。队列只允许在一端(队尾)进行插入操作,而在另一端(队头)进行删…

ant design vue做表单验证及form表单外验证、父子嵌套多个表单校验

1、form表单验证(若有时遇到输入框有值但是还是触发验证规则了&#xff0c;请检查form表单绑定正确吗、校验规则正确吗、表格数据字段名正确吗) <a-form:model"formState":label-col"{ span: 8 }":wrapper-col"{ span: 16 }":rules"rul…

flink设置保存点和恢复保存点

增加了hdfs package com.qyt;import org.apache.flink.api.java.functions.KeySelector; import org.apache.flink.api.java.tuple.Tuple2;import org.apache.flink.runtime.state.storage.FileSystemCheckpointStorage;import org.apache.flink.streaming.api.datastream.Dat…

《 Spring Boot实战:优雅构建责任链模式投诉处理业务》

Spring Boot实战&#xff1a;优雅构建责任链模式投诉处理业务 文章目录 Spring Boot实战&#xff1a;优雅构建责任链模式投诉处理业务场景描述&#xff1a;代码实现Step 1: 定义投诉请求类Step 2: 定义抽象处理者类Step 3: 实现具体的处理者类Step 4: 创建投诉处理链Step 5: 创…

基于Hive和Hadoop的哔哩哔哩网站分析系统

本项目是一个基于大数据技术的哔哩哔哩平台分析系统&#xff0c;旨在为用户提供全面的哔哩哔哩视频数据和深入的用户行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xf…

如何评估婚恋交友小程序的投资回报率

在这个数字化的时代&#xff0c;越来越多的人选择通过手机应用程序寻找自己的另一半。随着婚恋交友小程序的兴起&#xff0c;编辑h17711347205如何评估这类产品的投资回报率&#xff08;ROI&#xff09;成为了投资者和运营者关注的重点。本文将探讨如何有效地评估婚恋交友小程序…

如何构建鲁棒高性能 Prompt 的方法?

你好&#xff0c;我是三桥君 在当今时代&#xff0c;利用大型语言模型如ChatGPT进行文本生成和交互已成为一种趋势。然而&#xff0c;要充分发挥这些模型的能力&#xff0c;尤其是在生产环境中&#xff0c;我们需要精心设计和优化我们的提示词&#xff08;prompt&#xff09;。…

【C语言】动态内存管理:malloc、calloc、realloc、free

本篇介绍一下C语言中的malloc/calloc/realloc。 使用这些函数需要包含头文件<stdlib.h>。malloc/calloc/realloc申请的空间都是 堆区的。 1.malloc和free 1.1 malloc C语言提供了一个动态内存开辟的函数malloc&#xff0c;函数原型如下。 void* malloc(size_t size);…