C#设计模式(行为型模式):状态模式

C#设计模式:状态模式

在软件开发中,我们经常会遇到对象的行为取决于其状态的情况。例如,一个订单对象可能处于“待支付”、“已支付”、“已发货”等不同状态,而每个状态下订单的行为(例如是否可以支付、是否可以发货)是不同的。

传统的处理方式是使用大量的 if-elseswitch-case 语句来判断对象的状态,然后执行相应的行为。这种方式虽然直观,但随着状态数量的增加,代码会变得臃肿、难以维护,并且违背了开放-封闭原则。

状态模式 (State Pattern) 提供了一种优雅的解决方案,它将对象的状态抽象成独立的类,并将对象的行为委托给当前状态对象。这样,对象就可以在不同的状态下表现出不同的行为,而无需修改自身的代码。

一、状态模式的结构

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

  • Context(上下文): 定义客户感兴趣的接口,并维护一个具体状态对象的实例,该实例定义了对象的当前状态。
  • State(状态): 定义一个接口,用于封装与 Context 的特定状态相关的行为。
  • ConcreteState(具体状态): 实现 State 接口,每个具体状态类对应对象的一种状态,并实现该状态下的行为。

二、状态模式的实现

以下是一个简单的 C# 示例,演示如何使用状态模式实现一个订单系统:

// Context 类
public class Order
{
    private OrderState _state;

    public Order()
    {
        // 初始状态为待支付
        _state = new PendingPaymentState(this);
    }

    public void SetState(OrderState state)
    {
        _state = state;
    }

    public void Pay()
    {
        _state.Pay();
    }

    public void Ship()
    {
        _state.Ship();
    }

    public void Cancel()
    {
        _state.Cancel();
    }
}

// State 接口
public interface OrderState
{
    void Pay();
    void Ship();
    void Cancel();
}

// 具体状态类:待支付
public class PendingPaymentState : OrderState
{
    private Order _order;

    public PendingPaymentState(Order order)
    {
        _order = order;
    }

    public void Pay()
    {
        Console.WriteLine("订单支付成功!");
        _order.SetState(new PaidState(_order));
    }

    public void Ship()
    {
        Console.WriteLine("订单未支付,无法发货!");
    }

    public void Cancel()
    {
        Console.WriteLine("订单已取消!");
        _order.SetState(new CancelledState(_order));
    }
}

// 具体状态类:已支付
public class PaidState : OrderState
{
    private Order _order;

    public PaidState(Order order)
    {
        _order = order;
    }

    public void Pay()
    {
        Console.WriteLine("订单已支付,无需重复支付!");
    }

    public void Ship()
    {
        Console.WriteLine("订单发货成功!");
        _order.SetState(new ShippedState(_order));
    }

    public void Cancel()
    {
        Console.WriteLine("订单已支付,无法取消!");
    }
}

// 具体状态类:已发货
public class ShippedState : OrderState
{
    private Order _order;

    public ShippedState(Order order)
    {
        _order = order;
    }

    public void Pay()
    {
        Console.WriteLine("订单已发货,无法支付!");
    }

    public void Ship()
    {
        Console.WriteLine("订单已发货,无需重复发货!");
    }

    public void Cancel()
    {
        Console.WriteLine("订单已发货,无法取消!");
    }
}

// 具体状态类:已取消
public class CancelledState : OrderState
{
    private Order _order;

    public CancelledState(Order order)
    {
        _order = order;
    }

    public void Pay()
    {
        Console.WriteLine("订单已取消,无法支付!");
    }

    public void Ship()
    {
        Console.WriteLine("订单已取消,无法发货!");
    }

    public void Cancel()
    {
        Console.WriteLine("订单已取消,无需重复取消!");
    }
}

// 客户端代码
class Program
{
    static void Main(string[] args)
    {
        Order order = new Order();

        order.Pay();   // 输出:订单支付成功!
        order.Ship();  // 输出:订单发货成功!
        order.Cancel(); // 输出:订单已发货,无法取消!
    }
}

三、状态模式的优点

  • 将状态相关的行为局部化: 将与特定状态相关的行为封装在独立的类中,使得代码更加清晰、易于理解和维护。
  • 避免使用大量的条件语句: 通过将状态转换逻辑分散到各个状态类中,可以避免使用大量的 if-elseswitch-case 语句,提高代码的可读性和可维护性。
  • 方便添加新的状态: 如果需要添加新的状态,只需要创建新的具体状态类,并实现相应的行为即可,无需修改现有的代码,符合开放-封闭原则。

四、状态模式的适用场景

  • 对象的行为取决于其状态,并且状态数量较多。
  • 需要在运行时根据状态改变对象的行为。
  • 需要避免使用大量的条件语句来判断对象的状态。

五、总结

状态模式是一种非常有用的设计模式,它可以帮助我们更好地组织和管理对象的状态和行为。通过将状态抽象成独立的类,并将行为委托给当前状态对象,我们可以使代码更加清晰、易于理解和维护。

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

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

相关文章

R shiny app | 网页应用 空格分隔的文本文件在线转csv

shiny 能快速把R程序以web app的形式提供出来,方便使用,降低技术使用门槛。 本文提供的示例:把空格分隔的txt文件转为逗号分隔的csv文件。 前置依赖:需要有R环境(v4.2.0),安装shiny包(v1.9.1)。括号内是我使用的版本…

LLM - 使用 LLaMA-Factory 部署大模型 HTTP 多模态服务 教程 (4)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/144881432 大模型的 HTTP 服务,通过网络接口,提供 AI 模型功能的服务,允许通过发送 HTTP 请求,交互大模型,通常基于云计算架构,无需在本地部署复杂的模型和硬件,…

【《python爬虫入门教程11--重剑无峰168》】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 【《python爬虫入门教程11--selenium的安装与使用》】 前言selenium就是一个可以实现python自动化的模块 一、Chrome的版本查找?-- 如果用edge也是类似的1.chrome…

自定义Bitmap

使用场景 Bitmap 是一种使用 位数组(bit array) 来表示数据的结构,每一位(bit)表示一个值的状态。由于每个位只占用 1 bit,因此Bitmap 的存储效率非常高,特别适用于大数据去重、标记布尔值状态…

公司资产网站

本文结尾处获取源码。 本文结尾处获取源码。 本文结尾处获取源码。 一、相关技术 后端:Java、JavaWeb / Springboot。前端:Vue、HTML / CSS / Javascript 等。数据库:MySQL 二、相关软件(列出的软件其一均可运行) I…

第431场周赛:最长乘积等价子数组、计算字符串的镜像分数、收集连续 K 个袋子可以获得的最多硬币数量、不重叠区间的最大得分

Q1、最长乘积等价子数组 1、题目描述 给你一个由 正整数 组成的数组 nums。 如果一个数组 arr 满足 prod(arr) lcm(arr) * gcd(arr),则称其为 乘积等价数组 ,其中: prod(arr) 表示 arr 中所有元素的乘积。gcd(arr) 表示 arr 中所有元素的…

掌握RabbitMQ:全面知识点汇总与实践指南

前言 RabbitMQ 是基于 AMQP 高级消息队列协议的消息队列技术。 特点:它通过发布/订阅模型,实现了服务间的高度解耦。因为消费者不需要确保提供者的存在。 作用:服务间异步通信;顺序消费;定时任务;请求削…

国内Ubuntu环境Docker部署Stable Diffusion入坑记录

国内Ubuntu环境Docker部署Stable Diffusion入坑记录 本文旨在记录使用dockerpython进行部署 stable-diffusion-webui 项目时遇到的一些问题,以及解决方案,原项目地址: https://github.com/AUTOMATIC1111/stable-diffusion-webui 问题一览: …

SpringBoot3-深入理解自动配置类的原理(尚硅谷SpringBoot3-雷神)

文章目录 目录了解自动配置 一、导入对应场景的Mean依赖:1、引入依赖**找到自动配置类的所有配置都存放在哪里** 二、编写主程序:SpringBootApplication观察源码时所需要知道的几个核心注解:1、观察SpringBootApplication源码都做了什么 三、…

【沉默的羔羊心理学】汉尼拔的“移情”游戏:操纵与理解的艺术,精神分析学视角下的角色互动

终极解读《沉默的羔羊》:弗洛伊德精神分析学视角下的深层剖析 关键词 沉默的羔羊弗洛伊德精神分析学角色心理意识与潜意识性别与身份 弗洛伊德精神分析学简介 弗洛伊德的精神分析学是心理学的一个重要分支,主要关注人类行为背后的无意识动机和冲突。…

字玩FontPlayer开发笔记3 性能优化 大量canvas渲染卡顿问题

字玩FontPlayer开发笔记3 性能优化 大量canvas渲染卡顿问题 字玩FontPlayer是笔者开源的一款字体设计工具,使用Vue3 ElementUI开发,源代码: github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontpl…

javaEE-网络编程-3 UDP

目录 Socaket套接字 UDP数据报套字节编程 1.DatagrameSocket类 DatagramSocaket构造方法: DatagramSocaket常用方法: 2.DatagramPacket类 DatagramPacket构造方法: UDP回显服务器实现 UDP服务端实现: 创建一个Socket类对象&#xf…

Linux:操作系统不朽的传说

操作系统是计算机的灵魂,它掌控着计算机的硬件和软件资源,为用户和应用程序提供了一个稳定、高效、安全的运行环境。 在众多操作系统中,Linux 的地位举足轻重。它被广泛应用于服务器、云计算、物联网、嵌入式设备等领域。Linux 的成功离不开…

模拟出一个三维表面生成表面点,计算体积,并处理边界点

python代码 生成表面点,计算体积,并处理边界点,最终模拟出一个三维表面。 步骤: 初始参数设置: initial_fixed_point:一个初始固定点的坐标。 slop_thre:坡度阈值。 v_thre:体积阈值。 slope_rad:将坡度从度转换为弧度。 step_size:步长。 lam_x, lam_y:泊松分布的…

STM32拓展 低功耗案例1:睡眠模式 (register)

需求描述 让MCU进入睡眠模式,然后通过串口发送消息来唤醒MCU退出睡眠模式。观察LED在进入休眠模式后是否仍然开启。 思考 首先睡眠模式,唤醒的条件是中断,外部内部都可以,这里的串口接收中断时内部中断。 拓展:中断…

vue 基础参数增加多语言配置

js 对数组的增删改查 字段在数据库存储为nvarchar ,varchar存储波斯语会乱码 数组格式: {"en": [{"type": "10","value": "Confirm","color": ""},{"type": "…

[桌面运维]windows自动设置浅深色主题

设置自动浅色/深色主题 我看很多up主的教程过于繁琐,需要添加四个功能,并且有些还不能生效! 大多数都是教程: 自动任务栏浅色 add HKCUSOFTWAREMicrosoftWindowsCurrentVersionThemesPersonalize/v SystemUsesLightTheme /t …

[ubuntu-22.04]ubuntu不识别rtl8153 usb转网口

问题描述 ubuntu22.04插入rtl8153 usb转网口不识别 解决方案 安装依赖包 sudo apt-get install libelf-dev build-essential linux-headers-uname -r sudo apt-get install gcc-12 下载源码 Realtek USB FE / GBE / 2.5G / 5G Ethernet Family Controller Softwarehttps:/…

基于Python的考研学习系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

图漾相机基础操作

1.客户端概述 1.1 简介 PercipioViewer是图漾基于Percipio Camport SDK开发的一款看图软件,可实时预览相机输出的深度图、彩色图、IR红外图和点云图,并保存对应数据,还支持查看设备基础信息,在线修改gain、曝光等各种调节相机成像的参数功能…