首页 > 其他分享 >基于状态模式: 没有实践,再多的理论都是扯淡!!!

基于状态模式: 没有实践,再多的理论都是扯淡!!!

时间:2023-09-03 17:01:27浏览次数:37  
标签:状态 基于 console log 实践 扯淡 订单 发货 order

基于状态模式: 没有实践的理论都是扯淡!!!

基于状态模式: 没有实践,再多的理论都是扯淡!!!_初始化

定义

  • 状态模式是一种面向对象的设计模式,它允许一个对象在其内部状态改变时改变它对应的行为。
  • 状态模式的关键在于如何区分事物内部的状态,事物内部状态的改变往往会带来事物的行为的改变。
  • 通常我们谈到封装,一般都会优先封装对象的行为(比如,某个函数),而不是对象的状态。但在状态模式中恰好相反,状态模式的关键是把事物的每种状态都封装成单独的类,跟状态有关的行为会被封装在这个类的内部
之前读耗子叔文章时,看到过有句话说没有实践的理论都是扯淡,个人很赞同。那接下来让我们用代码说话,在实际应用中实践一下吧。

例子1:订单处理系统

  • 在订单处理系统中,每个订单都可以处于不同的状态(待处理,已确认,已发货,已完成, 已取消),且在每个状态下可执行不同的操作。
// 状态接口
class OrderState {
    constructor(order) {
        this.order = order;
    }

    // 定义状态方法
    confirm() {
        throw new Error("confirm() method must be implemented.");
    }

    cancel() {
        throw new Error("cancel() method must be implemented.");
    }

    ship() {
        throw new Error("ship() method must be implemented.");
    }
}

// 具体状态类:待处理状态
class PendingState extends OrderState {
    confirm() {
        console.log("订单已确认");
        this.order.setState(new ConfirmedState(this.order));
    }

    cancel() {
        console.log("订单已取消");
        this.order.setState(new CancelledState(this.order));
    }

    ship() {
        console.log("无法发货,订单未确认");
    }
}

// 具体状态类:已确认状态
class ConfirmedState extends OrderState {
    confirm() {
        console.log("订单已确认");
    }

    cancel() {
        console.log("订单已取消");
        this.order.setState(new CancelledState(this.order));
    }

    ship() {
        console.log("订单已发货");
        this.order.setState(new ShippedState(this.order));
    }
}

// 具体状态类:已发货状态
class ShippedState extends OrderState {
    confirm() {
        console.log("无法确认,订单已发货");
    }

    cancel() {
        console.log("无法取消,订单已发货");
    }

    ship() {
        console.log("订单已发货");
    }
}

// 具体状态类:已完成状态
class CompletedState extends OrderState {
    confirm() {
        console.log("无法确认,订单已完成");
    }

    cancel() {
        console.log("无法取消,订单已完成");
    }

    ship() {
        console.log("无法发货,订单已完成");
    }
}

// 具体状态类:已取消状态
class CancelledState extends OrderState {
    confirm() {
        console.log("无法确认,订单已取消");
    }

    cancel() {
        console.log("无法取消,订单已取消");
    }

    ship() {
        console.log("无法发货,订单已取消");
    }
}

// 上下文类:订单
class Order {
    constructor() {
        // 初始化状态
        this.currentState = new PendingState(this);
    }

    // 设置当前状态
    setState(state) {
        this.currentState = state;
    }

    // 执行确认操作
    confirm() {
        this.currentState.confirm();
    }

    // 执行取消操作
    cancel() {
        this.currentState.cancel();
    }

    // 执行发货操作
    ship() {
        this.currentState.ship();
    }
}

// 示例用法
const order = new Order();
order.confirm(); // 输出: 订单已确认
order.ship(); // 输出: 无法发货,订单未确认
order.cancel(); // 输出: 订单已取消
order.confirm(); // 输出: 订单已确认
order.ship(); // 输出: 订单已发货
order.confirm(); // 输出: 无法确认,订单已发货
order.cancel(); // 输出: 无法取消,订单已发货
order.ship(); // 输出: 订单已发货
order.confirm(); // 输出: 无法确认,订单已完成
  • 好了,我们可以来看下订单状态的流转过程:
  1. 初始状态(pending):当订单被创建后,订单处于待处理状态。此时可进行两个操作:确认(confirm)、取消(cancel) 。确认操作后可使状态转变为已确认状态,取消操作后可使状态转变为已取消状态。
  2. 已确认状态(confirm): 订单被确认后,此时可进行两种操作:取消(cancel)、发货(ship)。取消操作可使状态转变为已取消状态,发货操作可使状态转变为已发货状态。
  3. 已发货状态(ship): 订单发货后,无法在进行确认(confirm)操作,因为订单已经在路上了。此时可进行两个操作:取消(cancel)、发货(ship)。取消(cancel)操作可使状态转变为已取消状态,发货操作可使订单转变为已完成状态。
  4. 已完成状态(complete): 订单成功支付后,进入已完成状态。此时无法进行以下操作:确认(confirm)、取消(cancel)、发货(ship),因为订单已经完成
  5. 已取消状态(cancel): 订单被取消后,进入已取消状态,此时无法进行以下操作:确认(confirm)、取消(cancel)、发货(ship),因为订单已经取消

例子2:交通信号灯

// 信号灯状态基类
class TrafficLightState {
    constructor(light) {
        this.light = light;
    }

    // 状态行为方法,子类需要实现具体逻辑
    display() {}
    stopBlinking() {}
}

// 红灯状态
class RedLightState extends TrafficLightState {
    display() {
        console.log("红灯亮起");
        this.light.setState(new GreenLightState(this.light));
    }
}

// 绿灯状态
class GreenLightState extends TrafficLightState {
    display() {
        console.log("绿灯亮起");
        this.light.setState(new YellowLightState(this.light));
    }
}

// 黄灯状态
class YellowLightState extends TrafficLightState {
    display() {
        console.log("黄灯亮起");
        this.light.setState(new RedLightState(this.light));
    }
}

// 闪烁状态
class BlinkingLightState extends TrafficLightState {
    constructor(light) {
        super(light);
        this.intervalId = null;
    }

    display() {
        console.log("闪烁灯亮起");
        this.intervalId = setInterval(() => {
            this.light.toggle();
        }, 500);
    }

    stopBlinking() {
        console.log("闪烁灯停止");
        clearInterval(this.intervalId);
        this.light.setState(new RedLightState(this.light));
    }
}

// 信号灯类
class TrafficLight {
    constructor() {
        this.state = new RedLightState(this);
        this.isLightOn = false;
    }

    setState(state) {
        this.state = state;
    }

    display() {
        this.state.display();
    }

    toggle() {
        this.isLightOn = !this.isLightOn;
        console.log(`灯光${this.isLightOn ? "亮起" : "熄灭"}`);
    }

    stopBlinking() {
        this.state.stopBlinking();
    }
}

// 使用示例
const trafficLight = new TrafficLight();
trafficLight.display(); // 红灯亮起
trafficLight.display(); // 绿灯亮起
trafficLight.display(); // 黄灯亮起
trafficLight.setState(new BlinkingLightState(trafficLight));
trafficLight.display();
/**
灯光亮起
灯光熄灭
灯光亮起
灯光熄灭
灯光亮起
 */
setTimeout(() => {
    trafficLight.stopBlinking(); // 闪烁灯停止,变为红灯
}, 3000);
  • 这段代码的状态转移过程如下:
  1. 初始状态为红灯状态(RedLightState)。运行 trafficLight.display(); 会输出 "红灯亮起",并将状态设置为绿灯状态。
  2. 绿灯状态(GreenLightState)是红灯状态的下一个状态。运行 trafficLight.display(); 会输出 "绿灯亮起",并将状态设置为黄灯状态。
  3. 黄灯状态(YellowLightState)是绿灯状态的下一个状态。运行 trafficLight.display(); 会输出 "黄灯亮起",并将状态设置为闪烁状态。
  4. 闪烁状态(BlinkingLightState)是黄灯状态的下一个状态。运行 trafficLight.display(); 会输出 "闪烁灯亮起",并开始每隔 500 毫秒切换一次灯光状态,输出灯光状态信息。
  5. 在经过一定时间后,通过调用 trafficLight.stopBlinking(); 方法,闪烁状态会停止。输出 "闪烁灯停止",并将状态设置为红灯状态。

实例3:音频播放器

// 状态接口
class AudioPlayerState {
    constructor(audioPlayer) {
        this.audioPlayer = audioPlayer;
    }

    play() {}

    pause() {}

    stop() {}
}

// 停止状态
class StopState extends AudioPlayerState {
    play() {
        console.log('开始播放音频');
        // 切换到播放状态
        this.audioPlayer.setState(this.audioPlayer.playState);
    }

    pause() {
        console.log('音频已停止,无法暂停');
    }

    stop() {
        console.log('音频已停止');
    }
}

// 播放状态
class PlayState extends AudioPlayerState {
    play() {
        console.log('音频已经在播放中');
    }

    pause() {
        console.log('音频已暂停');
        // 切换到暂停状态
        this.audioPlayer.setState(this.audioPlayer.pauseState);
    }

    stop() {
        console.log('音频已停止');
        // 切换到停止状态
        this.audioPlayer.setState(this.audioPlayer.stopState);
    }
}

// 暂停状态
class PauseState extends AudioPlayerState {
    play() {
        console.log('音频已经在播放中');
    }

    pause() {
        console.log('音频已经暂停');
    }

    stop() {
        console.log('音频已停止');
        // 切换到停止状态
        this.audioPlayer.setState(this.audioPlayer.stopState);
    }
}

// 音频播放器类
class AudioPlayer {
    constructor() {
        // 初始化默认状态为停止状态
        this.stopState = new StopState(this);
        this.playState = new PlayState(this);
        this.pauseState = new PauseState(this);
        this.currentState = this.stopState;
    }

    setState(state) {
        this.currentState = state;
    }

    play() {
        this.currentState.play();
    }

    pause() {
        this.currentState.pause();
    }

    stop() {
        this.currentState.stop();
    }
}

// 示例用法
const audioPlayer = new AudioPlayer();

audioPlayer.play(); // 开始播放音频
audioPlayer.pause(); // 音频已暂停
audioPlayer.play(); // 音频已经在播放中
audioPlayer.stop(); // 音频已停止
audioPlayer.stop(); // 音频已停止
  • 大家可根据上面的例子可自行推理一下这段代码的状态转移过程。

状态模式的优缺点

  • 优点:
  1. 封装状态的变化:将每个状态封装成一个独立的类,使得状态转移的逻辑被封装在状态类中。这使得状态变化的逻辑与主体类分离,提高了代码的可维护性和可扩展性
  2. 简化条件语句:通过将状态判断和状态行为分离,避免了大量的条件语句。
  3. 符合开放——封闭原则:当添加新的状态时,不需要改变原有代码。
  4. 提高了代码的可扩展
  • 缺点:
  1. 增加了类的数量:引入状态模式会增加系统中的类的数量,每个状态都需要一个独立的类来表示,这会导致类的数量过多,增加了系统的复杂性。
  2. 状态转移逻辑复杂
  3. 不适合状态过多的情况

状态模式的性能优化点

  1. 惰性初始化:延迟初始化对象可减少启动时的开销,可将状态对象的创建延迟到真正需要的时候再进行初始化,而不是在启动时创建所有可能的状态对象
  2. 缓存状态对象:频繁的创建和销毁会严重影响性能,可使用对象池或缓存来管理状态对象的创建和复用
  3. 状态判断的优化:如果状态判断的逻辑复杂,可考虑使用策略模式来优化状态判断的性能
  4. 状态转移的优化:在状态的转换逻辑中可能会比较复杂,涉及多个条件的判断和状态变量的更新。可使用状态机或状态转换表来优化性能和可读性
  5. 状态对象的粒度优化:根据业务需要进行优化,若状态对象过于庞大会导致创建和切换状态开销较大,若状态对象过小,会增加状态类的数量和管理的复杂性。

状态模式和策略模式的关系

  • 两者就像一对双胞胎,都封装了一系列的算法或行为,他们看起来一模一样,但在意图上不同。
  • 两者的相同点是:都有上下文,一些策略和状态类,上下文把请求委托给这些类来执行
  • 区别是:在状态模式中,状态和状态对应的行为是早已被封装好的,状态之间的切换早已被规定完成,改变行为发生在状态模式的内部。而在策略模式中,他们之间没有任何联系,客户必须熟知这些策略类的作用,才能随时切换算法。

基于状态模式: 没有实践,再多的理论都是扯淡!!!_初始化_02

标签:状态,基于,console,log,实践,扯淡,订单,发货,order
From: https://blog.51cto.com/leadingcode/7341589

相关文章

  • 基于机器视觉的小车轨迹控制软件界面展示
    项目概述:硬件:USB摄像头、51单片机、L298N驱动、ESP2866-WiFi模块、移动电源软件:vs、c#、OpenCV、Socket通信软件:vs、c#、OpenCV、Socket通信**设计流程:**软件功能展示:自由模式循迹模式读取G指令写字......
  • 基于qsot库函数进行排序
    #include<stdio.h>#include<stdlib.h>intcmp_int(constvoid*e1,constvoid*e2){//进行比较return(int)e1-(int)e2;}intcmp_f(constvoid*e1,constvoid*e2){if((float)e1>(float)e2){return1;}elseif((float)e1==(float)e2){retu......
  • 基于Hugo的github个人博客的搭建
    一、前期准备以windows系统为例1.下载Git(https://git-scm.com/downloads)2.下载Hugo(https://github.com/gohugoio/hugo/releases)按照自己电脑下。3.设置环境变量:打开环境变量可以看到在系统变量有一个变量名为PATH的变量,直接点击然后编辑,把自己的git和hugo的位置添加进去。注意不是......
  • GO语言工程实践课后作业
    项目背景该项目是一个基于Gin框架开发的消息板应用,提供发布话题和回复功能。GinGin是一个基于Go语言的轻量级Web框架,它提供了快速构建高性能Web应用程序的工具和功能。以下是Gin框架的一些特点和使用方法:特点:快速:Gin是一个非常快速的框架,因为它使用了Radix树路由和高......
  • 基于风险的测试计划制定的步骤
    ①分析——识别风险,将风险进一步分解,确定优先级,排序。然后通过质量特性为桥梁,将仅与业务相关的风险与软件的特性联系起来。通过质量特性的分解和联系,方便后续步骤中设计测试策略。②选项、估算、平衡——此阶段实际上是一个循环改进的过程。对测试阶段进行合理安排,确定每个测试阶......
  • ubuntu宿主机和centos7虚拟机如何基于samba共享文件夹
    理论介绍要在Ubuntu宿主机和CentOS虚拟机之间设置基于Samba的文件夹共享,您可以按照以下步骤进行操作:在Ubuntu宿主机上:安装Samba服务器软件:sudoaptupdatesudoaptinstallsamba```````编辑Samba配置文件:sudonano/etc/samba/smb.conf```````在文件末尾添加以下内容来定义......
  • 【专题】2023AIGC应用与实践展望报告PDF合集分享(附原数据表)
    原文链接:https://tecdat.cn/?p=33544自2022年11月ChatGPT发布以来,其超出预期的“涌现”能力彻底点燃了AIGC赛道。从人力资源角度来看,AIGC相关职位数量明显增加,并且人才对于这些职位的投递也更加积极。阅读原文,获取专题报告合集全文,解锁文末190份AIGC行业相关报告。值得注意的是,A......
  • 【DBN分类】基于北方苍鹰算法优化深度置信网络NGO-DBN实现轴承故障分类matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • 基于SpringBoot的电商应用系统的设计与实现
    现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本电商应用系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的......
  • 基于SpringBoot的失物招领平台的设计与实现
    科学技术的不断发展,计算机的应用日渐成熟,其强大的功能给人们留下深刻的印象,它已经应用到了人类社会的各个层次的领域,发挥着重要的不可替换的作用。信息管理作为计算机应用的一部分,使用计算机进行管理,具有非常明显的优点。例如:方便快捷、高效率、低成本、存储量大、寿命长,这些优点能......