【状态模式】拯救if-else堆出来的屎山代码

这篇具有很好参考价值的文章主要介绍了【状态模式】拯救if-else堆出来的屎山代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

我想大家平时都在开发重都遇见过屎山代码,这些屎山代码一般都是由于复杂且庞大的if-else造成的,状态模式,是一种很好的优化屎山代码的设计模式,本文将采用两个业务场景的示例来讲解如何使用状态模式拯救屎山代码。

目录

前言

1.网购业务场景

1.1.需求

1.2.if else的实现

1.3.状态模式的实现

2.电梯业务场景

2.1.需求

2.2.if else的实现

2.3.状态模式的实现


1.网购业务场景

1.1.需求

我们来假设一个网购的业务场景,需求如下:

  • 流程为付款、再发货、在收货,流程必须按照以上顺序,也就是说发货后不能支付、收货后不能发货和支付

  • 付款后不能重复付款、发货后不能重复发货、收货后不能重复收货

1.2.if else的实现

这里我们设计一个Order订单类,用int型的state来表示状态,当然也可以用一个枚举类来表示状态会更规范一点,这里为了方便而已。

public class Order {
    //1 未付款
    //2 已付款
    //3 未发货
    //4 已发货
    //5 未收货
    //6 已收货
    private int state;
​
    public int getState() {
        return state;
    }
​
    public void setState(int state) {
        this.state = state;
    }
}

以收货方法为例,业务逻辑实现出来会是:

public void receive(Order order){
    if(order.getState()==2){
        if(order.getState()==4){
            if(order.getState()==5){
                System.out.println("收货成功");
            }else{
                System.out.println("已收货,无法重复收货");
            }
        }else{
            System.out.println("未发货");
        }
    }else{
        System.out.println("未付款");
    }
}

可以看到一座小屎山代码已经初具规模,但凡状态再多一点、业务逻辑再复杂一点,这座屎山将会基本不具备可读性。

1.3.状态模式的实现

其实仔细观察可以发现,很多时候状态往往是和实体的行为是相关的。之所以引入状态,我们是希望实体在不同的状态时呈现出不同的行为。

以上面的场景为例,在支付状态下,我们希望实体能呈现出支付相关的能力;在发货状态下呈现出发货相关的能力;在收货状态下呈现出收货相关的能力......

所以完全可以把状态和能力封装在一起,从而省掉外界的if-else判断,这就是所谓的状态模式。

状态模式总结起来一句话:

实体在不同的状态,拥有不同的行为。

作用是:

可以省掉大量判断条件带来的if-else逻辑分支,使得代码更简洁易读。

接下来我们用状态模式去改写之前的代码。

首先总结一下实体类会有的行为有哪些,其实就是付款、发货、收货,也就是三个方法,为了代码的规范,可以抽象出行为接口,当然不抽象也可以,仁者见仁智者见智。

public interface OrderState{
    void pay(Order order);
    void ship(Order order);
    void receive(Order order);
}

接下来总结一下系统里面的状态,订单有三个维度的六种状态,分别是:

  • 付款状态

    • 未付款

    • 已付款

  • 发货状态

    • 未发货

    • 已发货

  • 收货状态

    • 未收货

    • 已收货

于是可以得到有三个状态实体。

将状态和行为绑定,可以得到以下三个状态实体。

支付状态实体:

public class PayState implements OrderState{
    public void pay(Order order) {
        System.out.println("已支付,不能再次支付!");
    }
​
    public void ship(Order order) {
        order.setOrderState(new ShipState());
        System.out.println("已发货!");
    }
​
    public void receive(Order order) {
        System.out.println("未发货!不能收货!");
    }
}

发货状态实体:

public class ShipState implements OrderState{
    public void pay(Order order) {
        System.out.println("已发货!禁止重复支付!");
    }
​
    public void ship(Order order) {
        System.out.println("已经发货!禁止重复支付");
    }
​
    public void receive(Order order) {
        order.setOrderState(new ReceiveState());
        System.out.println("收货成功!");
    }
}

收货状态实体

public class ReceiveState implements OrderState{
    public void pay(Order order) {
        System.out.println("已收货,不能再次支付!");
    }
​
    public void ship(Order order) {
        System.out.println("已收货,不能再次发货!");
    }
​
    public void receive(Order order) {
        System.out.println("已收货,不能再次收货!");
    }
}

测试代码:

public class Test {
    public static void main(String[] args) {
        Order order=new Order();
        //初始状态未待支付
        order.setOrderState(new PayState());
        order.pay();
        order.ship();
        order.receive();
    }
}

测试结果:

【状态模式】拯救if-else堆出来的屎山代码,JAVA SE,java,设计模式,状态模式,原力计划

2.电梯业务场景

2.1.需求

我们考虑一个简单的电梯系统,其中有以下状态:

  1. 停止状态(StoppedState): 当电梯处于停止状态时,它可以接受移动到指定楼层的请求。

  2. 上升状态(MovingState): 当电梯处于上升状态时,它不能响应移动请求,因为它正在上升。

  3. 下降状态(MovingState): 当电梯处于下降状态时,它也不能响应移动请求,因为它正在下降。

规则:

  • 当电梯处于停止状态时,它可以接受移动到指定楼层的请求,并切换到移动状态(上升或下降)。

  • 当电梯处于上升状态或下降状态时,它不能接受移动请求,而是提示当前正在移动。

  • 电梯在移动过程中不能响应其他移动请求,直到它到达指定楼层并切换到停止状态。

在上面的业务情景中,我们通过使用状态模式对电梯系统进行了优化。每个状态(停止状态和移动状态)都对应一个状态类,并定义了在该状态下的行为。电梯状态的切换由上下文类(ElevatorStateContext)来管理,它负责在不同状态下执行不同的行为,并根据状态的变化进行切换。通过使用状态模式,我们将状态切换逻辑封装到不同的状态类中,使代码更加模块化和可扩展。文章来源地址https://www.toymoban.com/news/detail-650326.html

2.2.if else的实现

class ElevatorIfElse {
    private String state = "停止";
    private int currentFloor = 1;
​
    public void setState(String newState) {
        state = newState;
    }
​
    public void moveToFloor(int floor) {
        if (state.equals("停止")) {
            System.out.println("电梯从 " + currentFloor + " 楼移动到 " + floor + " 楼");
            currentFloor = floor;
        } else if (state.equals("上升")) {
            System.out.println("电梯正在上升,不能移动");
        } else if (state.equals("下降")) {
            System.out.println("电梯正在下降,不能移动");
        }
    }
}
​
public class MainIfElse {
    public static void main(String[] args) {
        ElevatorIfElse elevator = new ElevatorIfElse();
​
        elevator.moveToFloor(5);
        elevator.setState("上升");
        elevator.moveToFloor(3);
        elevator.moveToFloor(7);
        elevator.setState("停止");
        elevator.moveToFloor(2);
    }
}

2.3.状态模式的实现

interface ElevatorState {
    void moveToFloor(ElevatorStateContext context, int floor);
}
​
class StoppedState implements ElevatorState {
    @Override
    public void moveToFloor(ElevatorStateContext context, int floor) {
        System.out.println("电梯从 " + context.getCurrentFloor() + " 楼移动到 " + floor + " 楼");
        context.setCurrentFloor(floor);
        context.setState(new MovingState());
    }
}
​
class MovingState implements ElevatorState {
    @Override
    public void moveToFloor(ElevatorStateContext context, int floor) {
        System.out.println("电梯正在移动,不能移动");
    }
}
​
class ElevatorStateContext {
    private ElevatorState state;
    private int currentFloor = 1;
​
    public ElevatorStateContext() {
        this.state = new StoppedState();
    }
​
    public void setState(ElevatorState state) {
        this.state = state;
    }
​
    public void moveToFloor(int floor) {
        state.moveToFloor(this, floor);
    }
​
    public int getCurrentFloor() {
        return currentFloor;
    }
​
    public void setCurrentFloor(int currentFloor) {
        this.currentFloor = currentFloor;
    }
}
​
public class MainStatePattern {
    public static void main(String[] args) {
        ElevatorStateContext context = new ElevatorStateContext();
​
        context.moveToFloor(5);
        context.setState(new MovingState());
        context.moveToFloor(3);
        context.moveToFloor(7);
        context.setState(new StoppedState());
        context.moveToFloor(2);
    }
}

到了这里,关于【状态模式】拯救if-else堆出来的屎山代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java中使用工厂模式和策略模式优雅消除if-else语句(UML类图+案例分析)

     前言:在最近的后端开发中,多多少少会发现有很多if-else语句,如果条件过多则会造成整体代码看起来非常臃肿,这边我就举一个我在实际开发中的例子,来进行阐述这两种模式在实际开发中我是如何运用的。 目录 一、工厂模式简介 二、简单工厂模式 2.1、UML类图

    2024年02月15日
    浏览(33)
  • Python if-else 速记

    编程中经常使用速记符号来简化我们的工作。 速记符号是一种可以更简洁、更省时省力地完成工作的方法。 本文将讨论 Python 中使用的速记符号作为 if-else 语句的快捷方式。 如前所述,速记符号是一种可以简洁地编写程序的方法。 到目前为止,我们在 Python 中使用了许多速

    2024年02月11日
    浏览(43)
  • Python用if-else实现【猜数字】

    设置一个 范围1-100的随机整数变量 ,通过 while 循环,配合 input 语句,判断输入的数字是否等于随机数 无限次机会,直到猜中为止 每一次猜不中,会提示大了或小了 猜完数字后,提示猜了几次 提示: 无限次机会,终止条件不适合用数字累加来判断 可以考虑布尔类型本身 (

    2024年02月12日
    浏览(37)
  • mybatis使用xml中的if-else/choose

    最近需要使用 xml 文件来实现一些增删改查,此文对 其中的 if-else 加以说明 背景: 有一个引用类,假设叫 Student 现在我们查询条件也被封装成一个引用类,例如: 那么使用 xml 怎么来使用和接收呢? 首先肯定是在 mapper 里面有一个方法 然后在 xml 文件中写这个方法的具体实

    2024年04月23日
    浏览(36)
  • 条件运算符? : 与if-else语句的对比及用法详解

    条件运算符? : :给程序员提供了一种简便的方式进行条件判断和表达式的求值。在C语言中,条件运算符? : 是一个三元运算符,可以根据条件的真假来判断输出结果。本篇文章将详细介绍条件运算符的用法,以及与if-else语句的对比,并结合实例来进一步理解。 条件运算符?

    2024年02月05日
    浏览(49)
  • Verilog 不完整if-else和case产生锁存latch

    写这篇文章是因为本小白在刷题过程中看到答主的代码总是不把if-else写全,而我又记得不写全是可能产生latch的,对此很迷惑,仔细看过之后发现只有组合逻辑(电平触发)电路中的不完整if-else和case才会产生锁存器latch。简单记录一下。 参考文章: 1、https://blog.csdn.net/ainu

    2024年02月13日
    浏览(66)
  • ASIC-WORLD Verilog(8)if-else语句和case语句

            在自己准备写一些简单的verilog教程之前,参考了许多资料----Asic-World网站的这套verilog教程即是其一。这套教程写得极好,奈何没有中文,在下只好斗胆翻译过来(加了自己的理解)分享给大家。         这是网站原文:Verilog Tutorial         这是系列导航:

    2024年02月01日
    浏览(46)
  • 🔥🔥Java开发者的Python快速进修指南:控制之if-else和循环技巧

    在我们今天的学习中,让我们简要了解一下Python的控制流程。考虑到我们作为有着丰富Java开发经验的程序员,我们将跳过一些基础概念,如变量和数据类型。如果遇到不熟悉的内容,可以随时查阅文档。但在编写程序或逻辑时,if-else判断和循环操作无疑是我们经常使用的基

    2024年02月05日
    浏览(61)
  • 设计模式:干掉if else的几种方法

    存在的问题: 如果业务逻辑过多 if else 可能要写多达几百行,这样代码可读性很差,不利于寻找bug和理解代码 如果if后面的判断逻辑过长,则代码可读性不强 如果将其写在一个核心代码里面,则新增功能时需要修改核心代码,要是不小心改到其他的代码就凉凉了 当业务逻辑

    2024年02月07日
    浏览(38)
  • 策略模式+Spring配置类优化多if..else思路

    场景: 假设设备上报不同类型的消息,我们要对不同类型的消息做不同的处理。如果我们通过if..else的方式处理的话会显得比较冗余。 例如: 那么对于不同消息的不同的处理逻辑我们可以单独放在一个实现类中,这些类有着相同的行为,所以我们可以定义一个接口: 针对于不

    2024年02月15日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包