设计模式 行为型 状态模式(State Pattern)与 常见技术框架应用 解析

news2025/1/11 8:32:40

在这里插入图片描述

状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,使得对象看起来好像修改了它的类。这种设计模式的核心思想是将对象的状态和行为封装成不同的状态类,通过状态对象的行为改变来避免大量的条件判断语句,从而提升代码的可扩展性和可维护性。

一、核心思想

状态模式的核心思想是将状态相关的行为抽取到独立的状态类中,使得增加新状态变得简单,且不影响其他状态。每个状态类都封装了对象在该状态下的行为,上下文类(Context)则维护一个状态对象,并在状态发生变化时改变其行为。

二、定义与结构

定义

状态模式(State Pattern)是行为设计模式的一种,它允许一个对象在其内部状态改变时改变它的行为。

结构

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

  • State(状态):定义一个接口或抽象类,用于封装与上下文相关的行为。
  • ConcreteState(具体状态):实现状态接口或继承抽象状态类,具体定义每个状态下的行为。
  • Context(上下文):维护一个状态对象,并在状态发生变化时改变其行为。

三、角色

  • 环境角色(Context):也称为上下文,它定义了客户程序与状态对象交互的接口,并且保存了一个具体状态对象的引用。
  • 抽象状态(State):这是一个接口或抽象类,定义了所有具体状态所共有的一些行为。
  • 具体状态(Concrete States):这些是实现了抽象状态接口的具体类,每个类代表了一个状态,并且在该状态下定义了一些行为。

四、实现步骤及代码示例

以Java为例,状态模式的实现步骤通常包括:

  1. 定义状态接口:定义一个接口,用于封装与上下文相关的行为。
  2. 创建具体状态类:实现状态接口,具体定义每个状态下的行为。
  3. 定义上下文类:维护一个状态对象,并提供方法来切换状态和处理请求。

以下是一个简单的Java代码示例,用于展示状态模式的实现:

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

// 具体状态类:待支付状态
class PendingState implements State {
    @Override
    public void handle() {
        System.out.println("订单状态:待支付。请完成支付!");
    }
}

// 具体状态类:已支付状态
class PaidState implements State {
    @Override
    public void handle() {
        System.out.println("订单状态:已支付。订单处理中。");
    }
}

// 具体状态类:已完成状态
class CompletedState implements State {
    @Override
    public void handle() {
        System.out.println("订单状态:已完成。");
    }
}

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

    public OrderContext() {
        this.state = new PendingState(); // 初始状态为待支付
    }

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

    public void handleOrder() {
        state.handle();
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        OrderContext orderContext = new OrderContext();
        orderContext.handleOrder(); // 输出:订单状态:待支付。请完成支付!

        orderContext.setState(new PaidState());
        orderContext.handleOrder(); // 输出:订单状态:已支付。订单处理中。

        orderContext.setState(new CompletedState());
        orderContext.handleOrder(); // 输出:订单状态:已完成。
    }
}

五、常见技术框架应用

1、前端框架中状态模式的应用

状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态发生改变时改变其行为。在前端框架中,状态模式的应用十分广泛,特别是在管理复杂的用户交互逻辑和页面状态时。以下是一些前端框架中应用状态模式的举例:

购物车状态管理

在电商网站的购物车页面中,商品的状态(如已添加、已删除、数量变化等)会影响购物车的整体行为和显示。使用状态模式,可以清晰地管理这些状态变化。

  • 状态定义:定义购物车状态的抽象类,如CartState,并为其定义添加商品、删除商品等抽象方法。
  • 具体状态类:创建具体的状态类,如EmptyCartState(空购物车状态)和NonEmptyCartState(非空购物车状态),在这些类中实现具体的行为。
  • 购物车类:在购物车类中,维护一个当前状态的引用,并根据状态的变化调用相应的方法。

例如,在购物车为空时,用户只能添加商品;在购物车非空时,用户可以查看商品列表、删除商品等。通过状态模式,可以轻松地管理这些状态变化,使代码更加清晰和可维护。

表单验证状态管理

在用户提交表单之前,需要对表单中的输入进行验证。使用状态模式,可以根据不同的验证状态(如有效、无效、必填项未填写等)来改变表单的行为。

  • 状态定义:定义表单验证状态的抽象类,如FormValidationState,并为其定义验证方法。
  • 具体状态类:创建具体的状态类,如ValidState(有效状态)、InvalidState(无效状态)和RequiredFieldMissingState(必填项未填写状态),在这些类中实现具体的验证逻辑。
  • 表单类:在表单类中,维护一个当前验证状态的引用,并根据状态的变化调用相应的方法来处理验证结果。

游戏状态管理

在游戏中,对象的状态可能会随着游戏的进程而发生变化,如角色的生命值、能量值、游戏阶段等。使用状态模式,可以轻松地管理这些状态变化。

  • 状态定义:定义游戏状态的抽象类,如GameState,并为其定义更新、渲染等方法。
  • 具体状态类:创建具体的状态类,如IdleState(空闲状态)、PlayingState(游戏进行状态)、GameOverState(游戏结束状态),在这些类中实现具体的游戏逻辑。
  • 游戏管理类:在游戏管理类中,维护一个当前游戏状态的引用,并根据状态的变化调用相应的方法来处理游戏逻辑。

UI组件状态管理

在前端开发中,一些UI组件(如按钮、输入框、下拉菜单等)的状态可能会随着用户的交互而发生变化。使用状态模式,可以清晰地管理这些状态变化。

  • 状态定义:定义UI组件状态的抽象类,如ComponentState,并为其定义更新、渲染等方法。
  • 具体状态类:创建具体的状态类,如HoverState(悬停状态)、ActiveState(激活状态)、DisabledState(禁用状态),在这些类中实现具体的UI逻辑。
  • 组件类:在组件类中,维护一个当前状态的引用,并根据状态的变化调用相应的方法来处理UI逻辑。

前端路由状态管理

在单页面应用(SPA)中,前端路由的状态管理是一个重要的问题。使用状态模式,可以清晰地管理路由的状态变化。

  • 状态定义:定义路由状态的抽象类,如RouteState,并为其定义导航、回退等方法。
  • 具体状态类:创建具体的状态类,如HomeState(首页状态)、DetailState(详情页状态)等,在这些类中实现具体的导航逻辑。
  • 路由管理类:在路由管理类中,维护一个当前路由状态的引用,并根据状态的变化调用相应的方法来处理导航逻辑。

综上所述,状态模式在前端框架中的应用十分广泛,可以用于管理复杂的用户交互逻辑、页面状态、游戏状态以及UI组件状态等。通过状态模式,可以使代码更加清晰、可维护和可扩展。

2、 Android 中的 View 状态

  • 在Android开发中,View(如Button)有多种状态,比如“正常状态”、“按下状态”、“不可用状态”等。这些状态的行为和外观是不同的。
// 定义抽象状态接口(简化版)
interface ViewState {
    void onDraw(Canvas canvas);
    boolean onTouchEvent(MotionEvent event);
}
// 正常状态类
class NormalState implements ViewState {
    @Override
    public void onDraw(Canvas canvas) {
        // 绘制正常状态下的视图外观
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // 切换到按下状态
            view.setState(view.getPressedState());
            return true;
        }
        return false;
    }
}
// 按下状态类
class PressedState implements ViewState {
    @Override
    public void onDraw(Canvas canvas) {
        // 绘制按下状态下的视图外观
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            // 切换到正常状态或者执行点击操作等
            view.setState(view.getNormalState());
            return true;
        }
        return false;
    }
}
// 自定义View(环境类)
class CustomView extends View {
    private ViewState state;
    private ViewState normalState;
    private ViewState pressedState;
    public CustomView(Context context) {
        super(context);
        normalState = new NormalState();
        pressedState = new PressedState();
        state = normalState;
    }
    @Override
    protected void onDraw(Canvas canvas) {
        state.onDraw(canvas);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return state.onTouchEvent(event);
    }
    public void setState(ViewState state) {
        this.state = state;
        invalidate();
    }
    public ViewState getState() {
        return state;
    }
    public ViewState getNormalState() {
        return normalState;
    }
    public ViewState getPressedState() {
        return pressedState;
    }
}

六、应用场景

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

  1. 必须在对象运行时改变对象的行为。
  2. 传统编程需要考虑所有可能发生的情况,使用条件选择语句if-else判断并选择执行。当新增状态时,需要新增if-else语句,程序扩展繁琐。针对条件表达式过于复杂,可以采用状态模式,分离判断逻辑变为一系列的状态类,使判断逻辑变得更加简单。

七、优缺点

优点

  1. 封装性强:每个状态都被封装成一个类,使得状态逻辑更加清晰,便于维护和扩展。
  2. 避免条件语句:通过状态模式可以避免使用大量的条件语句来控制对象的行为,使代码更加简洁和可读。
  3. 增强可扩展性:可以轻松地添加新的状态类,而不需要修改已有的代码,从而增强了系统的可扩展性。

缺点

  1. 状态类过多可能导致复杂性增加:如果系统中存在大量的状态类,可能会导致状态类之间的关系变得复杂,增加系统的理解和维护成本。
  2. 状态切换可能不够灵活:在某些情况下,状态切换可能受到限制,无法满足特定的业务需求。

综上所述,状态模式是一种非常有用的设计模式,可以有效地管理对象的状态和行为,并实现状态之间的转换逻辑。在实际应用中,应根据具体业务需求来设计状态类和上下文类,以确保模式的正确应用和系统的稳定性。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2274817.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SAP SD学习笔记27 - 贩卖契约(框架协议)2 - 基本契约 - 金额契约(价值合同)

上一章讲了贩卖契约(框架协议)的概要,以及贩卖契约中最为常用的 基本契约 - 数量契约。 SAP SD学习笔记26 - 贩卖契约(框架协议)的概要,基本契约 - 数量契约-CSDN博客 本章继续讲SAP中的内容: - 基本契约 - 金额契约…

mysql之基本select语句 运算符 排序分页

1.SQL的分类 DDL:数据定义语言. CREATE ALTER DROP RENAME TRUNCATE DML: 数据操作语言. INSERT DELETE UPDATE SELECT 重中之重 DCL: 数据控制语言. COMMIT ROLLBACK SAVEPOINT GRANT REVOKE 2.SQL语言的规则与规范 1.基本规则 SQL可以在一行或多行,为了提高可…

Linux中SSH服务(二)

一、基于公私钥的认证(免密登录) 1、Windows免密登录Linux Windows推荐安装Cygwin软件:Cygwin 1.1Windows上面生成公私钥 之前已经生成过了,所以显示公私钥已存在 lovezywLAPTOP-AABHB5ED ~ $ ssh-keygen Generating public/pr…

.NET Core NPOI 导出图片到Excel指定单元格并自适应宽度

NPOI:支持xlsx,.xls,版本>2.5.3 XLS:HSSFWorkbook,主要前缀HSS, XLSX:XSSFWorkbook,主要前缀XSS,using NPOI.XSSF.UserModel; 1、导出Excel添加图片效果&#xff0…

NS2202X 系列 40V 输入 OVP 保护 IC

1 特性  最大输入电压: 40V  内部预设 2.1A 负载过流 OCP 保护  外置过流保护阈值可调节引脚,可悬空  外置 EN 使能控制引脚  内部预设 6V 输入过压 OVP 保护  输入 OVP 保护响应时间 20ns  内置 150 ℃过温…

Web前端基础知识(七)

要在JS中获取元素节点&#xff0c;需要使用DOM API提供的方法。 innerHTML&#xff1a;不仅会返回一个纯文本&#xff0c;还可以解析一下这个文本中的语意。 innerText: 忽略HTML标记。 举例&#xff1a; <body> <div id"box1">这是一个ID选择器标签…

[Transformer] The Structure of GPT, Generative Pretrained Transformer

The Structure of Generative Pretrained Transformer Reference: The Transformer architecture of GPT models How GPT Models Work

欧拉公式和傅里叶变换

注&#xff1a;英文引文机翻&#xff0c;未校。 中文引文未整理去重&#xff0c;如有异常&#xff0c;请看原文。 Euler’s Formula and Fourier Transform Posted byczxttkl October 7, 2018 Euler’s formula states that e i x cos ⁡ x i sin ⁡ x e^{ix} \cos{x} i …

【python基础——异常BUG】

什么是异常(BUG) 检测到错误,py编译器无法继续执行,反而出现错误提示 如果遇到错误能继续执行,那么就捕获(try) 1.得到异常:try的执行,try内只可以捕获一个异常 2.预案执行:except后面的语句 3.传入异常:except … as uestcprint(uestc) 4.没有异常:else… 5.鉴定完毕,收尾的语…

Python 模块 Uvicorn 实战指南

文章目录 1. 介绍和安装1.1 介绍1.2 安装 2. 创建基础应用2.1 简单的 HTTP 应用2.2 添加日志 3. 实现高级功能3.1 支持 WebSocket3.2 优化运行性能 4. Nginx 配置反向代理4.1 安装与配置 Nginx4.2 启用 SSL 支持4.3 性能优化建议 5. 常见问题与解决方案5.1 高并发问题5.2 WebSo…

音频数据增强:提升音频信号质量的多种技术

在音频处理和机器学习领域&#xff0c;音频数据增强是一种常用的技术&#xff0c;旨在通过对原始音频信号进行各种变换和处理&#xff0c;生成更多样化的训练数据。   这不仅可以提高模型的鲁棒性&#xff0c;还能改善其在真实世界应用中的表现。本文将介绍几种常用的音频数据…

uniapp vue2版本如何设置i18n

如何设置i18n在该软件设置过语言的情况下优先选择所设置语言&#xff0c;在没有设置的情况下&#xff0c;获取本系统默认语言就&#xff0c;将系统默认语言设置为当前选择语言。 1、下载依赖&#xff1a; npm install vue-i18n --save 2、创建相关文件&#xff08;在最外层&…

vulnhub靶场【DC系列】之9 the final 结束篇

前言 靶机&#xff1a;DC-8&#xff0c;IP地址为192.168.10.11&#xff0c;后续因为靶机重装&#xff0c;IP地址变为192.168.10.13 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.2 都采用VMWare&#xff0c;网卡为桥接模式 对于文章中涉及到的靶场以及工具&#xf…

网络安全 | 网络安全法规:GDPR、CCPA与中国网络安全法

网络安全 | 网络安全法规&#xff1a;GDPR、CCPA与中国网络安全法 一、前言二、欧盟《通用数据保护条例》&#xff08;GDPR&#xff09;2.1 背景2.2 主要内容2.3 特点2.4 实施效果与影响 三、美国《加利福尼亚州消费者隐私法案》&#xff08;CCPA&#xff09;3.1 背景3.2 主要内…

基于QT和C++的实时日期和时间显示

一、显示在右下角 1、timer.cpp #include "timer.h" #include "ui_timer.h" #include <QStatusBar> #include <QDateTime> #include <QMenuBar> Timer::Timer(QWidget *parent) :QMainWindow(parent),ui(new Ui::Timer) {ui->setup…

STM32小实验2

定时器实验 TIM介绍 TIM&#xff08;Timer&#xff09;定时器 定时器可以对输入的时钟进行计数&#xff0c;并在计数值达到设定值时触发中断 16位计数器、预分频器、自动重装寄存器的时基单元&#xff0c;在72MHz计数时钟下可以实现最大59.65s的定时 不仅具备基本的定时中断…

【软考】软件设计师

「学习路线」&#xff08;推荐该顺序学习&#xff0c;按照先易后难排序&#xff09; 1、上午题—计算机系统&#xff08;5~6分&#xff09;[1.8; ] 2、上午题—程序设计语言&#xff08;固定6分&#xff09;[1.9; ] 3、下午题—试题一&#xff08;15分&#xff09; 4、上午题—…

2030年中国AI人才缺口或达400万,近屿智能助力AI人才储备增长

在当今数字化浪潮下&#xff0c;人工智能&#xff08;AI&#xff09;已成为推动各行业发展的关键力量。然而&#xff0c;吸引和留住 AI 人才正成为全球性难题&#xff0c;中国亦不例外。据麦肯锡 2022 年全球人工智能商业高管调查&#xff0c;75% 的中国受访者在招聘数据科学家…

一块钱的RISC-V 32位芯片

‍‍ ‍‍之前跟一个朋友聊天&#xff0c;说以后的芯片一定是越来越趋向于定制化&#xff0c;比如我们需要一个ADC芯片&#xff0c;这颗ADC芯片需要有串口功能&#xff0c;那就只开发一颗这样的芯片就好了&#xff0c;其他的功能都可以裁剪掉。 ➵➵➵➵➵➵➵➵➵➵➵➵➵➵➵…

rk3568平台Buildroot编译实践:内核rootfs定制 及常见编译问题

目录 编译前准备常规编译流程定制内核修改内核 参数并增量 保存修改rootfs并增量 保存修改rootfs包下载源rootfs软件包增删refBuildroot 是一个用于自动化构建嵌入式 Linux 系统的工具。它通过使用简单的配置文件和 Makefile,能够从源代码开始交叉编译出一个完整的、可以运行在…