设计模式行为型-状态模式

news2025/1/21 15:32:19

文章目录

  • 简介
  • 状态模式基础
    • 定义状态接口或抽象类
      • 实现具体状态类
  • 上下文类与状态转换
    • 上下文类的定义和作用
    • 状态转换及触发条件
  • 状态模式的优势与适用性
    • 优点一:可维护的代码
    • 优点二:清晰的状态管理
    • 适用场景一:对象拥有多个状态
    • 适用场景二:状态转换频繁且复杂
  • 具体业务场景应用:电商订单状态切换
  • 状态模式与其他设计模式的结合
    • 策略模式与状态模式的对比与联系
    • 工厂模式与状态模式的结合实践
  • 总结

简介

  • 状态模式是一种行为型设计模式,用于处理对象在不同状态下的行为变化。它将对象的行为封装在不同状态类中,通过状态的切换实现不同行为的触发。
  • 本文将介绍状态模式的基本概念、应用场景以及优势与适用性。
    在这里插入图片描述

状态模式基础

定义状态接口或抽象类

public abstract class State
    {
        public abstract void WriteProgram(Work w);
    }

实现具体状态类

    //上午工作状态
    public class ForenoonState : State
    {
        public override void WriteProgram(Work w)
        {
//这里的判断就是决定要用那种行为展现出来,如果 不符合当前状态,那么就去到已经设置好的下一个具体状态类中进行相同的操作。
            if (w.hour < 12)
            {
                Console.WriteLine("当前时间:{0}点 上午工作,精神百倍",w.Hour);
            }
            else
            {
                w.SetState(new NoonState());w.WriteProgram();
            }
        }
    }
    //中午工作状态
    public class NoonState : State
    {
        public override void WriteProgram(Work w)
        {
            if (w.hour < 13)
            {
                Console.WriteLine("当前时间:{0}点 饿了,想吃饭;犯困,想睡觉。", w.Hour);
            }
            else
            {
                w.SetState(new AfternoonState()); w.WriteProgram();
            }
        }
    }
    //下午工作状态
    public class AfternoonState : State
    {
        public override void WriteProgram(Work w)
        {
            if (w.hour < 17)
            {
                Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力", w.Hour);
            }
            else
            {
                w.SetState(new EveningState()); w.WriteProgram();
            }
        }
    }
    //晚上工作状态
    public class EveningState : State
    {
        public override void WriteProgram(Work w)
        {
            if (w.finish )
            {
                w.SetState(new RestState());w.WriteProgram();//完成任务就转成下班状态
            }
            else
            {
                if (w.hour <21)
                {
                    Console.WriteLine("当前时间:{0}点 加班了,加班人累啊", w.Hour);
                }
                else 
                {
                    w.SetState(new SleepingState()); w.WriteProgram();//超过21点,转入睡眠状态
                }
            }
        }
    }

    //睡眠状态
    public class SleepingState:State
    {
        public override void WriteProgram(Work w)
        {
            Console.WriteLine("当前时间:{0}点 不行了,睡着了", w.Hour);
        }
    }
    //下班休息状态
    public class RestState : State
    {
        public override void WriteProgram(Work w)
        {
            Console.WriteLine("当前时间:{0}点 不行了,睡着了", w.Hour);
        }
    }

具体工作类:

    public class Work
    {
        public State current;
        
        public Work()
        {
            current = new ForenoonState();	//初始化为上午9点开始上班
        }
        public double hour;//小时钟,状态转换的依据

        public bool finish = false;//完成任务属性,是否能下班的依据
 
 
//这个方法主要就是把具体的状态类给进来,然后让下面的方法去使用
        public void SetState(State s)	//得到状态
        {
            current = s;
        }
//下面这个方法从始至终都没有发生改变,改变是其内部具体的展现值。
        public void WriteProgram() 
        {
            current.WriteProgram(this);
        }
    }

上下文类与状态转换

上下文类的定义和作用

  • 上下文类包含状态对象的引用,并将具体行为委托给当前状态对象执行。
  • 示例代码:
// 上下文类
public class Context {
    private State currentState;

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

    public void request() {
        // 委托当前状态对象执行行为
        currentState.handle();
    }
}

状态转换及触发条件

  • 状态转换指从一个状态切换到另一个状态的过程。
  • 触发条件是使状态转换发生的条件。
  • 示例代码:
// 具体状态类A
public class ConcreteStateA implements State {
    // ...

    @Override
    public void handle() {
        // 具体状态A的行为逻辑

        // 状态转换及触发条件
        if (/*触发条件*/) {
            context.setCurrentState(new ConcreteStateB());
        }
    }
}

状态模式的优势与适用性

优点一:可维护的代码

  • 状态模式将每个状态的行为逻辑封装在独立的状态类中,易于理解和维护。

优点二:清晰的状态管理

  • 状态模式通过上下文类进行状态转换和行为委托,使状态管理更加清晰明确。

适用场景一:对象拥有多个状态

  • 当对象具有多个状态且不同状态下表现出不同行为时,可以使用状态模式进行状态管理和行为切换。

适用场景二:状态转换频繁且复杂

  • 当状态转换频繁且存在复杂的触发条件时,状态模式能够提供一种结构化的方式来管理状态转换。

具体业务场景应用:电商订单状态切换


为了演示订单状态管理的状态模式业务代码,我将使用Java语言来实现。以下是一个简单的示例:

首先,我们定义订单状态接口 OrderState,其中包含了处理订单状态的方法 handle()

// 订单状态接口
public interface OrderState {
    void handle();
}

然后,我们创建具体的订单状态类,包括待支付状态、已支付状态、待发货状态和已发货状态。每个状态类实现了订单状态接口,并根据相应的状态实现了自己的行为逻辑。

// 待支付状态类
public class PendingPaymentState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:待支付");
        // 处理待支付状态的逻辑
    }
}

// 已支付状态类
public class PaidState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:已支付");
        // 处理已支付状态的逻辑
    }
}

// 待发货状态类
public class ToBeShippedState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:待发货");
        // 处理待发货状态的逻辑
    }
}

// 已发货状态类
public class ShippedState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:已发货");
        // 处理已发货状态的逻辑
    }
}

接下来,我们创建订单类 Order,它包含了当前订单状态和一些操作方法。

// 订单类
public class Order {
    private OrderState currentState; // 当前订单状态

    public Order() {
        currentState = new PendingPaymentState(); // 默认初始状态为待支付
    }

    public void setCurrentState(OrderState state) {
        currentState = state;
    }

    public void request() {
        currentState.handle();
    }
}

最后,我们可以进行测试,模拟订单在不同状态下的行为变化:

public class Main {
    public static void main(String[] args) {
        Order order = new Order(); // 创建订单

        // 待支付状态
        order.request();

        // 支付订单,状态转换为已支付
        order.setCurrentState(new PaidState());
        order.request();

        // 发货,状态转换为待发货
        order.setCurrentState(new ToBeShippedState());
        order.request();

        // 完成发货,状态转换为已发货
        order.setCurrentState(new ShippedState());
        order.request();
    }
}

运行以上代码,将得到如下输出:
在这里插入图片描述

以上示例演示了订单状态管理的状态模式业务代码。通过状态模式,我们可以根据订单状态的变化触发不同的行为逻辑,并且可以方便地添加新的订单状态,以满足业务需求。

状态模式与其他设计模式的结合

策略模式与状态模式的对比与联系

策略模式和状态模式都属于行为型设计模式,它们都关注对象在不同的情境下具有不同的行为。虽然它们有相似之处,但在设计意图、应用场景和实现方式上存在一些差异。

下面是策略模式和状态模式的对比与联系:

对比:

  1. 设计意图:策略模式旨在通过定义一组算法或策略,并将其封装成独立的对象,使得这些算法可以互换使用。状态模式旨在让一个对象在其内部状态改变时改变其行为,从而实现状态之间的转换。

  2. 关注点:策略模式主要关注算法的选择和封装,使得具体的策略可以独立于客户端进行变化。状态模式主要关注对象的状态的管理和转换,以及不同状态下的行为执行。

  3. 对象角色:策略模式通常包含一个上下文类(Context)和一组策略类(Strategies),客户端与上下文类进行交互。状态模式通常包含一个上下文类(Context)和一组状态类(States),客户端与上下文类进行交互。

联系:

  1. 行为的封装:策略模式和状态模式都将行为封装到独立的对象中,使得行为可以被动态地变化。

  2. 对象之间的互动:策略模式和状态模式都需要一个上下文类(Context)来与策略对象或状态对象进行交互,并将具体的行为委托给策略对象或状态对象来执行。

  3. 可扩展性:策略模式和状态模式都具有较好的可扩展性。在策略模式中,可以方便地新增、修改或切换不同的策略对象。在状态模式中,可以方便地新增、修改或切换不同的状态对象。

总的来说,策略模式和状态模式都是强调对象行为的灵活性和可扩展性的设计模式。它们的主要区别在于策略模式关注算法的选择和封装,而状态模式关注对象状态的管理和转换。根据具体的需求,选择适合的模式来提高代码的可维护性和可扩展性。

工厂模式与状态模式的结合实践

  • 结合工厂模式可以实现状态类的动态创建和切换,增强了状态模式的灵活性和可扩展性。
    结合工厂模式可以实现状态类的动态创建和切换,从而增强了状态模式的灵活性和可扩展性。工厂模式可以将状态对象的创建和状态转换逻辑与客户端代码分离,使得系统更加可维护和可扩展。

下面是一个示例,演示了如何结合工厂模式和状态模式来管理订单的状态:

首先,定义订单状态接口 OrderState 和具体的订单状态类,与之前的示例相同。

// 订单状态接口
public interface OrderState {
    void handle();
}

// 待支付状态类
public class PendingPaymentState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:待支付");
        // 处理待支付状态的逻辑
    }
}

// 已支付状态类
public class PaidState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:已支付");
        // 处理已支付状态的逻辑
    }
}

// 待发货状态类
public class ToBeShippedState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:待发货");
        // 处理待发货状态的逻辑
    }
}

// 已发货状态类
public class ShippedState implements OrderState {
    @Override
    public void handle() {
        System.out.println("当前订单状态:已发货");
        // 处理已发货状态的逻辑
    }
}

然后,创建一个工厂类 OrderStateFactory,用于动态创建订单状态对象。
在严格意义上这个工厂是一个不支持扩充的,但是在这里仅作为一个示例,如果想要真正达到动态创建还是需要用到工厂方法,这里只能算是一个简单工厂。

// 订单状态工厂类  
public class OrderStateFactory {
    public static OrderState createOrderState(String stateName) {
        switch (stateName.toLowerCase()) {
            case "pendingpayment":
                return new PendingPaymentState();
            case "paid":
                return new PaidState();
            case "tobeshipped":
                return new ToBeShippedState();
            case "shipped":
                return new ShippedState();
            default:
                throw new IllegalArgumentException("Invalid state name");
        }
    }
}

接下来,我们可以使用上述的状态类和工厂类进行订单状态切换的实践:

public class Main {
    public static void main(String[] args) {
        Order order = new Order(); // 创建订单

        // 设置待支付状态
        order.setCurrentState(OrderStateFactory.createOrderState("PendingPayment"));
        order.request();

        // 支付订单,切换到已支付状态
        order.setCurrentState(OrderStateFactory.createOrderState("Paid"));
        order.request();

        // 发货,切换到待发货状态
        order.setCurrentState(OrderStateFactory.createOrderState("ToBeShipped"));
        order.request();

        // 完成发货,切换到已发货状态
        order.setCurrentState(OrderStateFactory.createOrderState("Shipped"));
        order.request();
    }
}

通过工厂模式,我们可以根据状态名称动态地创建不同的订单状态对象,并将其设置为上下文类的当前状态。这样,如果要新增或修改订单状态,只需要修改工厂类的代码,而不需要修改客户端的代码。这增强了状态模式的灵活性和可扩展性。

总结

  • 状态模式是一种有助于管理对象不同状态下行为变化的设计模式。通过将状态和行为封装在不同状态类中,状态模式提供了一种结构化的方式来处理状态转换和行为委托。它适用于对象拥有多个状态且状态转换复杂的场景,并与其他设计模式如策略模式、工厂模式等相结合能够进一步扩展其功能和灵活性。

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

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

相关文章

分享一个非常有趣的纯css杂志封面折叠效果

&#x1f60a;博主&#xff1a;小猫娃来啦 &#x1f60a;文章核心&#xff1a;有趣的纯css杂志封面折叠效果 文章目录 效果出处效果HTMLCSS 效果出处 这个css杂志封面折叠效果非常有趣&#xff0c;我就转载加以记录。 效果来源于&#xff1a;码上掘金Mad Magazine 效果 HTML…

硬件系统工程师宝典(38)-----常用接口之视频接口的电路设计

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。 上篇我们介绍了一些常用的接口带EMC保护的电路设计&#xff0c;有AC24V、AC110~220V、AV接口、CAN接口、DC12V、DC24V、DC48V接口。今天我们来讲一…

vulhub之MinIO信息泄露漏洞(CVE-2023-28432)

文章目录 0x01 前言0x02 漏洞描述0x03 影响范围0x04 漏洞复现1.启动环境2.查看端口3.构造POC 0x05 修复建议 0x01 前言 本次测试仅供学习使用&#xff0c;如若非法他用&#xff0c;与本文作者无关&#xff0c;需自行负责&#xff01;&#xff01;&#xff01; 0x02 漏洞描述 …

攻防世界-web-fakebook

1. 题目描述 打开链接&#xff0c;这样一个界面 貌似没啥特殊的。。。没关系&#xff0c;我们每个页面都点击一下 login页面&#xff1a;一个简单的登录页面 join界面&#xff1a;不出意外&#xff0c;这应该是一个注册界面 目前&#xff0c;我们什么都不做&#xff0c;能获…

文本匹配实战系列

引言 本系列文章开始介绍深度学习在文本匹配领域的应用&#xff0c;并且会尝试得到各种模型在给定的数据集上的表现。 深度文本匹配发展比较久&#xff0c;积累了很多文本匹配方法。也有很多的分类方式&#xff0c;一种分类方式是表示型和交互型。 表示型方法 表示型(repre…

上海亚商投顾:沪指缩量震荡 数据要素概念午后爆发

上海亚商投顾前言&#xff1a;无惧大盘涨跌&#xff0c;解密龙虎榜资金&#xff0c;跟踪一线游资和机构资金动向&#xff0c;识别短期热点和强势个股。 市场情绪 沪指今日延续反弹&#xff0c;深成指、创业板指盘中涨超1%&#xff0c;随后上演冲高回落走势。数据要素概念午后爆…

universal robot 机械臂 官方基本教程

https://academy.universal-robots.cn/modules/e-Series-core-track/Chinese/module3/story_html5.html?courseId2166&languageChinese 教程1 控制箱内部 包含&#xff1a; 主机板&#xff0c;SD卡&#xff0c;和安全控制板 安全控制板负责所有控制信息&#xff0c;包括…

Android需要掌握的shell脚本基础

linux中sh是链接到bash上的&#xff0c;所以sh与bash在功能上是没有区别的&#xff0c;相当于bash解析器是sh的增强版本&#xff0c;所以安卓开发者可以在 git bash中 测试脚本 1&#xff0c;shell脚本运行与输出指令 $ cat test.sh echo 测试 【输出】$ /bin/bash test.…

Spring框架知识点汇总

01.Spring框架的基本理解 关键字&#xff1a;核心思想IOC/AOP&#xff0c;作用&#xff08;解耦&#xff0c;简化&#xff09;&#xff0c;简单描述框架组成&#xff1b; Spring框架是一款轻量级的开发框架&#xff0c;核心思想是IOC&#xff08;反转控制&#xff09;和AOP&a…

【操作系统】聊聊局部性原理是如何提升性能的

对于目前数据主导的系统&#xff0c;大多数都是Java/Go 技术栈MySQL&#xff0c;但是随着时间的推移&#xff0c;数据库数据的数据量过多&#xff0c;并且会频繁访问热点数据&#xff0c;为了提升系统的性能&#xff0c;一般都是加入缓存中间件、Redis。 局部性原理 我们知道…

Pytorch学习:神经网络模块torch.nn.Module和torch.nn.Sequential

文章目录 1. torch.nn.Module1.1 add_module&#xff08;name&#xff0c;module&#xff09;1.2 apply(fn)1.3 cpu()1.4 cuda(deviceNone)1.5 train()1.6 eval()1.7 state_dict() 2. torch.nn.Sequential2.1 append 3. torch.nn.functional.conv2d 1. torch.nn.Module 官方文档…

python的可哈希对象

一、介绍 在Python中&#xff0c;可哈希&#xff08;hashable&#xff09;是指一种对象类型&#xff0c;该类型的对象可以用作字典的键&#xff08;keys&#xff09;或集合&#xff08;sets&#xff09;的元素。可哈希的对象具有以下特点&#xff1a; 不可变性&#xff08;Imm…

【Interaction交互模块】LinearTransformDrive线性变换驱动

文章目录 一、预设位置二、案例&#xff1a;建一个按下后可自动抬起的按钮三、留有疑问 一、预设位置 交互——可控制物体——变换——线性变换驱动 二、案例&#xff1a;建一个按下后可自动抬起的按钮 按钮的结构和设置如下图 为了让它碰触时&#xff0c;往下走——预设体…

【Go 基础篇】Go语言结构体基本使用

在Go语言中&#xff0c;结构体是一种重要的数据类型&#xff0c;用于定义和组织一组不同类型的数据字段。结构体允许开发者创建自定义的复合数据类型&#xff0c;类似于其他编程语言中的类。本文将深入探讨Go语言中结构体的定义、初始化、嵌套、方法以及与其他语言的对比&#…

Java八股文学习笔记day01

01.和equals区别 对于字符串变量来说&#xff0c;使用""和"equals"比较字符串时&#xff0c;其比较方法不同。""比较两个变量本身的值&#xff0c;即两个对象在内存中的首地址&#xff0c;"equals"比较字符串包含内容是否相同。 对于非…

VR司法法治教育平台,沉浸式课堂教学培养刑侦思维和能力

VR司法法治教育平台提供了多种沉浸式体验&#xff0c;通过虚拟现实(Virtual Reality&#xff0c;简称VR)技术让用户深度参与和体验法治知识。以下是一些常见的沉浸式体验&#xff1a; 1.罪案重现 VR司法法治教育平台可以通过重现真实案例的方式&#xff0c;让用户亲眼目睹罪案发…

基于天鹰算法优化的BP神经网络(预测应用) - 附代码

基于天鹰算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于天鹰算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.天鹰优化BP神经网络2.1 BP神经网络参数设置2.2 天鹰算法应用 4.测试结果&#xff1a;5.Matlab代码 摘要…

Python 的画图函数 seaborn 简介

seaborn 简介 seanborn 是 Python 的另外一个常用工具包&#xff0c;它基于 matplotlib&#xff0c;但画出的图形更加美观些&#xff0c;并且与 Pandas 的数据类型结合地较好。 # Import seaborn import seaborn as sns import matplotlib.pyplot as plt# Apply the default …

选择一款可靠的仓库管理软件

在选择仓库管理软件时&#xff0c;数据的准确性、数据的安全性和软件的稳定性这三点是至关重要的。下面我们将详细讨论这些关键点。 第一&#xff0c;数据的准确性对于一个仓库管理软件来说是非常重要的。如果数据的准确性无法得到保证&#xff0c;那么这样的仓库入库出库管理…

华为OD七日集训第1期复盘 - 按算法分类,由易到难,循序渐进,玩转OD(文末送书)

目录 一、活动内容如下第1天、逻辑分析第2天、字符串处理第3天、数据结构第4天、双指针第5天、递归回溯第6天、二分查找第7天、贪心算法 && 二叉树 二、可观测性工程1、简介2、主要内容 大家好&#xff0c;我是哪吒。 最近一直在刷华为OD机试的算法题&#xff0c;坚持…