状态模式的理解和实践

        在软件开发中,我们经常遇到需要根据对象的不同状态执行不同行为的情况。如果直接将这些状态判断和行为逻辑写在同一个类中,会导致该类变得臃肿且难以维护。为了解决这个问题,状态模式(State Pattern)应运而生。状态模式是一种行为设计模式,它允许对象在内部状态改变时改变它的行为,避免了大量的条件分支语句,使代码更加清晰和易于管理。

 

一、状态模式的基本概念

        状态模式的核心思想是将对象的行为封装在不同的状态对象中,每个状态对象都有一个共同的抽象状态基类。对象的行为随着其内部状态的改变而改变,而状态的改变是通过状态对象之间的转换来实现的。

        状态模式包含以下几个角色:

  1. Context(环境类):持有当前状态对象的引用,可以维护一个状态对象,并在需要的时候委托状态对象处理请求。
  2. State(抽象状态类):定义一个接口,用于封装与Context的一个特定状态相关的行为。
  3. ConcreteState(具体状态类):实现抽象状态类,每个具体状态类对应Context的一个具体状态,并在其中实现与该状态相关的行为。

二、状态模式的优点

  1. 结构清晰:将状态相关的行为封装在状态类中,避免了大量的条件分支语句,使代码更加清晰。
  2. 易于扩展:新增状态或修改状态行为时,只需新增或修改状态类,无需修改Context类。
  3. 符合开闭原则:对扩展开放,对修改关闭。

三、状态模式的缺点

  1. 类数目增多:状态类数目较多,增加了系统的复杂性。
  2. 状态转换逻辑复杂:如果状态转换逻辑复杂,状态类之间的依赖关系可能会变得复杂。

四、状态模式的实践

        下面我们以一个简单的例子来演示状态模式的应用。假设我们有一个订单系统,订单有不同的状态:待支付、已支付、已发货、已完成。每个状态下订单的行为是不同的,例如待支付状态下可以支付,已支付状态下可以发货,已发货状态下可以确认收货等。

1. 定义抽象状态类

        首先,我们定义一个抽象状态类OrderState,它包含一个处理请求的方法handle

public abstract class OrderState {
    protected OrderContext orderContext;

    public OrderState(OrderContext orderContext) {
        this.orderContext = orderContext;
    }

    public abstract void handle(String request);
}


2. 定义具体状态类

        然后,我们为每个状态定义一个具体状态类,例如PendingPaymentStatePaidStateShippedStateCompletedState

public class PendingPaymentState extends OrderState {
    public PendingPaymentState(OrderContext orderContext) {
        super(orderContext);
    }

    @Override
    public void handle(String request) {
        if ("pay".equals(request)) {
            System.out.println("Order is being paid...");
            orderContext.setState(new PaidState(orderContext));
            System.out.println("Order has been paid.");
        } else {
            System.out.println("Invalid request for this state: " + request);
        }
    }
}

public class PaidState extends OrderState {
    public PaidState(OrderContext orderContext) {
        super(orderContext);
    }

    @Override
    public void handle(String request) {
        if ("ship".equals(request)) {
            System.out.println("Order is being shipped...");
            orderContext.setState(new ShippedState(orderContext));
            System.out.println("Order has been shipped.");
        } else {
            System.out.println("Invalid request for this state: " + request);
        }
    }
}

public class ShippedState extends OrderState {
    public ShippedState(OrderContext orderContext) {
        super(orderContext);
    }

    @Override
    public void handle(String request) {
        if ("confirm".equals(request)) {
            System.out.println("Order is being confirmed...");
            orderContext.setState(new CompletedState(orderContext));
            System.out.println("Order has been completed.");
        } else {
            System.out.println("Invalid request for this state: " + request);
        }
    }
}

public class CompletedState extends OrderState {
    public CompletedState(OrderContext orderContext) {
        super(orderContext);
    }

    @Override
    public void handle(String request) {
        System.out.println("Order is already completed. No further actions can be taken.");
    }
}


3. 定义环境类

        接下来,我们定义环境类OrderContext,它持有当前状态对象的引用,并在需要的时候委托状态对象处理请求。

public class OrderContext {
    private OrderState state;

    public OrderContext() {
        this.state = new PendingPaymentState(this);
    }

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

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

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

        orderContext.handle("pay");
        orderContext.handle("ship");
        orderContext.handle("confirm");
        orderContext.handle("confirm"); // Invalid request for this state
    }
}


4. 运行结果

        运行OrderContextmain方法,输出结果如下:

Order is being paid...
Order has been paid.
Order is being shipped...
Order has been shipped.
Order is being confirmed...
Order has been completed.
Invalid request for this state: confirm


总结

        状态模式通过将对象的行为封装在不同的状态对象中,使对象的行为随着其内部状态的改变而改变。状态模式避免了大量的条件分支语句,使代码更加清晰和易于维护。同时,状态模式也符合开闭原则,对扩展开放,对修改关闭。

        在实际应用中,状态模式适用于对象的行为依赖于其状态,并且状态之间可以相互转换的场景。例如,订单处理系统、工作流引擎、游戏角色状态管理等。

        需要注意的是,状态模式会增加类的数目,并且如果状态转换逻辑复杂,状态类之间的依赖关系可能会变得复杂。因此,在使用状态模式时,需要权衡其优缺点,根据具体场景选择合适的设计模式。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux篇】权限管理 - 用户与组权限详解

一. 什么是权限? 首先权限是限制人的。人 真实的人 身份角色 权限 角色 事物属性 二. 认识人–用户 Linux下的用户分为超级用户和普通用户 root :超级管理员,几乎不受权限的约束普通用户 :受权限的约束超级用户的命令提示符是#,普通用…

Java刷题常见的集合类,各种函数的使用以及常见的类型转化等等

前言 相信大家在刷算法题的过程中,好不容易想出来大概的思路,也知道去用哪个集合类,但各个集合类的一些命令都长得太像,很容易将他们弄错,并且在各集合之间的转化也是特别烦人,还有很多实用的函数都知道可…

cgo内存泄漏排查

示例程序&#xff1a; package main/* #include <stdlib.h> #include <string.h> #include <stdio.h> char* cMalloc() {char *mem (char*)malloc(1024 * 1024 * 16);return mem; } void cMemset(char* mem) {memset(mem, -, 1024 * 1024 * 16); } int arr…

【算法】【优选算法】位运算(下)

目录 一、&#xff1a;⾯试题 01.01.判定字符是否唯⼀1.1 位图1.2 hash思路1.3 暴力枚举 二、268.丢失的数字2.1 位运算&#xff0c;异或2.2 数学求和 三、371.两整数之和四、137.只出现⼀次的数字 II五、⾯试题 17.19.消失的两个数字 一、&#xff1a;⾯试题 01.01.判定字符是…

Tomcat 都有哪些核心组件

优质博文&#xff1a;IT-BLOG-CN 【1】Server&#xff1a;Server元素在最顶层&#xff0c;代表整个 Tomcat容器&#xff0c;因此他必须是 server.xml中唯一一个最外层的元素。一个 Server元素可以有一个或多个 Service元素。 <Server port"8005" shutdown"…

前端开发 之 15个页面加载特效中【附完整源码】

前端开发 之 15个页面加载特效中【附完整源码】 文章目录 前端开发 之 15个页面加载特效中【附完整源码】八&#xff1a;圆环百分比加载特效1.效果展示2.HTML完整代码 九&#xff1a;毒药罐加载特效1.效果展示2.HTML完整代码 十&#xff1a;无限圆环加载特效1.效果展示2.HTML完…

单张照片生成3D互动场景:李飞飞团队AI 3D技术引领未来

近日,由斯坦福大学教授李飞飞领导的团队推出了一项革命性的AI 3D重建技术,该技术能够从多张未知姿态的照片中自动生成高质量的3D互动场景。这项技术不仅标志着计算机视觉领域的一大进步,也为元宇宙虚拟空间、沉浸式看房、XR(扩展现实)+文旅等应用带来了新的可能性。 技术…

洛谷P2670扫雷游戏(Java)

三.P2670 [NOIP2015 普及组] 扫雷游戏 题目背景 NOIP2015 普及组 T2 题目描述 扫雷游戏是一款十分经典的单机小游戏。在 n 行 m列的雷区中有一些格子含有地雷&#xff08;称之为地雷格&#xff09;&#xff0c;其他格子不含地雷&#xff08;称之为非地雷格&#xff09;。玩…

【机器学习】机器学习的基本分类-监督学习-决策树-CART(Classification and Regression Tree)

CART&#xff08;Classification and Regression Tree&#xff09; CART&#xff08;分类与回归树&#xff09;是一种用于分类和回归任务的决策树算法&#xff0c;提出者为 Breiman 等人。它的核心思想是通过二分法递归地将数据集划分为子集&#xff0c;从而构建一棵树。CART …

商汤完成组织架构调整,改革完成的商汤未来何在?

首先&#xff0c;从核心业务的角度来看&#xff0c;商汤科技通过新架构明确了以AI云、通用视觉模型等为核心业务的战略方向。这一举措有助于商汤科技集中资源&#xff0c;加强在核心业务领域的研发和市场拓展&#xff0c;提高市场竞争力。同时&#xff0c;坚定生成式AI为代表的…

python学opencv|读取视频(二)制作gif

【1】引言 前述已经完成了图像和视频的读取学习&#xff0c;本次课学习制作gif格式动图。 【2】教程 实际上想制作gif格式动图是一个顺理成章的操作&#xff0c;完成了图像和视频的处理&#xff0c;那就自然而然会对gif的处理也产生兴趣。 不过在opencv官网、matplotlib官网…

【Pytorch】torch.reshape与torch.Tensor.reshape区别

问题引入&#xff1a; 在Pytorch文档中&#xff0c;有torch.reshape与torch.Tensor.reshape两个reshape操作&#xff0c;他们的区别是什么呢&#xff1f; 我们先来看一下官方文档的定义&#xff1a; torch.reshape&#xff1a; torch.Tensor.reshape: 解释&#xff1a; 在p…

ArcGIS对地区进行筛选提取及投影转换

首先我们需要对坐标系和投影这些概念做进一步的解释。 1、基本概念&#xff1a; 想要理解坐标系和投影的概念&#xff0c;首先我们需要先理解什么是坐标。顾名思义&#xff0c;坐标就是指我们所在的位置&#xff0c;比如我在离旗杆东北部50m处&#xff0c;其实就是离旗杆东边…

qt QRadialGradient详解

1、概述 QRadialGradient是Qt框架中QGradient的一个子类&#xff0c;它用于创建径向渐变效果。径向渐变是从一个中心点向外扩散的颜色渐变&#xff0c;通常用于模拟光源或创建类似于高光和阴影的效果。QRadialGradient允许你定义渐变的中心点、焦距&#xff08;控制渐变扩散的…

Docker--Docker Image(镜像)

什么是Docker Image&#xff1f; Docker镜像&#xff08;Docker Image&#xff09;是Docker容器技术的核心组件之一&#xff0c;它包含了运行应用程序所需的所有依赖、库、代码、运行时环境以及配置文件等。 简单来说&#xff0c;Docker镜像是一个轻量级、可执行的软件包&…

《C++ Primer Plus》学习笔记|第1章 预备知识 (24-12-2更新)

文章目录 1.2.4 1.4 程序创建1.4.2 编译和链接 1.2.4 泛型编程 它允许程序员在编写代码时不指定具体的数据类型&#xff0c;而是使用一种通用的模板来处理多种不同的数据类型。以提高代码的复用性 C模板提供了完成这种任务的机制。 1.4 程序创建 使用文本编辑器编写程序&…

string类函数的手动实现

在上一篇文章中&#xff0c;我们讲解了一些string类的函数&#xff0c;但是对于我们要熟练掌握c是远远不够的&#xff0c;今天&#xff0c;我将手动实现一下这些函数~ 注意&#xff1a;本篇文章中会大量应用复用&#xff0c;这是一种很巧妙的方法 和以往一样&#xff0c;还是…

架构06-分布式共识

零、文章目录 架构06-分布式共识 1、分布式共识 &#xff08;1&#xff09;基本概念 **分布式共识&#xff1a;**在分布式系统中&#xff0c;多个节点之间达成一致的过程。**复杂性来源&#xff1a;**网络的不可靠性和请求的并发性。**应用场景&#xff1a;**如何确保重要数…

USB 声卡全解析:提升音频体验的得力助手

在当今数字化的时代&#xff0c;音频领域的追求愈发多元。无论是热衷聆听高品质音乐的爱好者&#xff0c;还是在专业音频工作中精雕细琢的人士&#xff0c;亦或是在游戏世界里渴望极致音效沉浸的玩家&#xff0c;都始终在寻觅能让音频体验更上一层楼的妙法。而 USB 声卡&#x…

系统--线程互斥

1、相关背景知识 临界资源多线程、多执行流共享的资源,就叫做临界资源临界区每个线程内部,访问临界资源的代码互斥在任何时刻,保证有且只有一个执行流进入临界区,访问临界资源,对临界资源起到保护作用原子性不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么…