22207321-王郅坚-第三次BLOG

前言

这两次电器控制系统的开发迭代,涵盖了不同的编程知识点、设计思路与系统逻辑。第一次迭代实现了一个基础的电器控制系统,通过简单的电器类型和基本操作设置,实现了电器状态的管理与切换。这一阶段主要考察基本数据结构的使用、输入输出处理、以及简单的判断与循环逻辑。为了提升用户体验,系统需要能够处理用户的输入并输出电器状态。但在实现中,系统对错误输入的处理还不够健全,导致用户在输入错误时遭遇崩溃的问题。

第二次迭代的设计复杂度有所提升,除了扩展电器类型外,还引入了电器之间的连接关系与状态管理,使得系统的功能更加贴合实际应用场景。在此迭代中,我学习了面向对象编程(OOP)的设计思想,重新构建了电器管理模块以实现更清晰的逻辑和功能划分。同时,加入了对输入格式的校验、异常处理等功能,使得系统在面对复杂用户输入时更具健壮性。这两次迭代的不同不仅提升了我的编程能力,也让我体会到在开发过程中的迭代设计思维和系统化组织的重要性。

三次迭代的实质性变化与思路简述

第一次迭代:基础电器控制系统构建

在第一次迭代中,我实现了一个基本的电器控制系统,包括几种电器(如开关、风扇、灯泡等),主要逻辑集中在输入的读取、状态的切换及输出的展示上。本次迭代的重点在于:

  • 数据结构的应用:使用基本的数据结构如ArrayListHashMap来存储电器及其状态。
  • 线性逻辑实现:代码结构相对简单,功能明确,没有过多复杂的逻辑分支。此时,系统的功能运行较为稳定,但缺乏坚实的输入校验,用户输入的错误可能导致系统崩溃。

第二次迭代:功能扩展与复杂性管理

在第二次迭代中,我在首次迭代的基础上进行了功能强化与复杂场景的处理。本次迭代关注于:

  • 面向对象设计的引入:采用类和继承的形式构建更复杂的电器系统,通过不同的电器类来体现各自的特性。子类实现各自特定的行为和状态逻辑,增强了代码的可复用性。
  • 输入格式化与状态管理:通过引入输入格式的验证与状态的动态管理,应对复杂的业务场景。在用户输入时增加了对电器连接与控制逻辑的检测,避免了因输入不规范导致的混乱。
  • 复杂业务的处理:引入了电器连接管理的概念,使得电器之间的相互作用能够被清晰地定义与运行。进一步增强了系统对不同业务场景的适应性。

题目集七

一、功能设计

该程序是一个电器控制系统,通过命令行模拟对多种电器(如开关、风扇、灯泡等)的控制逻辑。功能设计主要包括:

  1. 电器类别管理:每个电器通过不同的子类继承自Electric类,具体实现各自特性和操作。
  2. 命令输入与解析:用户可以输入电器的连接和操作,通过正则表达式解析命令,建立电路连接。
  3. 状态更新与计算:根据用户提供的指令更新电器的状态,计算电压、速度等属性。
  4. 结果输出:按特定格式输出每个电器的当前状态,便于用户查看。

二、代码结构分析

  1. 类设计

    • Electric 类是所有电器的基类,定义了电器的基本属性和方法,包含电压、开关状态等:
    class Electric {
        public String type; // 类型
        public String id; // 类型id
        public double voltage = 220; // 默认电压
        public String state = "turned on"; // 默认开关状态
        // 其他属性和构造函数
    }
    
    • 每个电器类型(如 Switch、SpeedController 等)通过继承 Electric 实现具体的行为。
  2. 方法实现分析

    • Switch 类中的 setVoltage 方法根据开关状态设置电压:
    public void setVoltage(double voltage) {
        this.voltage = state.equals("turned on") ? 0 : voltage; // 如果开关打开,电压为 0
    }
    
    • SpeedController 类在 regulate 方法中控制风速:
    public void regulate(String value) {
        if (value.equals("+") && speed < 3) {
            speed++; // 增加风速
        } else if (value.equals("-") && speed > 0) {
            speed--; // 降低风速
        }
    }
    
    • getLuminance 方法在 IncandescentLamp 类中计算灯泡的亮度,依赖当前电压:
    public int getLuminance() {
        if (voltage <= 9) return 0; // 亮度等于 0
        if (voltage <= 219) return (int) (voltage * (200.0 / 220)); // 线性变化
        return 200; // 最大亮度
    }
    
  3. 输入解析

    • main 方法中,输入通过正则表达式解析,并存储连接关系与操作指令:
    if (s.startsWith("#T")) {
        connection.add(s); // 存储串联连接
    } else if (s.startsWith("#M")) {
        connection1.add(s); // 存储并联连接
    } else {
        chw.add(s); // 存储操作指令
    }
    

三、时间复杂度

  1. 输入解析:O(n),n为输入的行数。
  2. 设备添加与存储:平均情况下,假设每条命令处理一次,时间复杂度为 O(m),m 为设备数量。
  3. 电流与电压计算:对于每个设备,可能需要遍历所有电器,复杂度为 O(e),e为电器的数量。

因此,整体时间复杂度为 O(n + m + e)。

四、空间复杂度

  • 该程序使用多个集合存储电器及连接关系,空间复杂度为 O(e + n),其中 e 为电器数量,n 为输入行数。

五、圈复杂度

  • 圈复杂度主要受控制结构(如循环和条件分支)的影响,特别是在switch语句中,存在多个较深的嵌套和条件判断,导致较高的复杂度。
switch (type) {
    case "K": return 7;
    case "F": return 6;
    // 省略细节
}

每个电器的状态更新与显示也可能涉及多个条件分支,设计时应考虑简化逻辑。

六、详细代码分析

  1. 电器类实现

    • Electric类是核心,设计得较为清晰,提供了基本的功能,但方法中缺少注释会影响理解:
    public void regulate(String value) {} // 预留给子类实现
    
  2. 设备状态更新

    • main 中对电器状态进行更新的逻辑较为复杂,尤其是在遍历连接和操作命令时,代码的可读性不高。
    for (String command : chw) {
        if (command.startsWith("#K")) {
            // 更新开关状态
        } else if (command.startsWith("#F")) {
            // 更新风扇状态
        }
    }
    
  3. 计算和展示

    • 输出电器状态时,所有设备依次调用 display 方法实现各自的输出,采用了多态优势。

以下是题目七的类图,展示了我的代码是如何设计类以及方法的使用:

再是我的顺序图在这个顺序图中,我们展示了以下步骤:

七、踩坑心得

  1. 正则表达式的使用

    • 正则表达式解析输入时未处理输入格式错误,可能导致后续逻辑不正确。建议在解析前加入输入验证。
  2. 逻辑清晰度

    • 状态更新逻辑涉及多个条件判断时,建议使用更简单的结构或策略设计模式,降低复杂性。
  3. 异常处理

    • 对于输入解析及设备状态更新,缺乏足够的错误处理,当输入格式不正确时,可能导致程序崩溃,应通过异常捕获处理。

八、改进措施

  1. 增强输入校验

    • 检查用户输入,确保格式正确,在解析开始前应增加对格式的校验和异常处理。
  2. 逻辑重构

    • 对复杂的方法进行分解,将逻辑拆分为多个小的方法,使其易于管理和理解。例如,将命令解析、设备状态更新等逻辑分开封装。
  3. 增加文档和注释

    • 为主要逻辑添加注释,明确每段代码的功能,以便代码的可维护性和可理解性。

九、收获与不足

收获

  • 深入理解了面向对象设计的基本原则,如继承和多态在电器控制系统中的具体应用。
  • 学会使用正则表达式进行复杂字符串处理,提高了对输入管理的灵活性。

不足

  • 代码复杂性较高,尤其在状态更新时,处理逻辑繁琐,增加了出错的可能性。
  • 缺乏对输入的健壮性检查,未能妥善处理无效输入,提高系统稳定性的能力不足。

结论

该电器控制系统展现了良好的设计思路与实现方法,涵盖了类的继承与多态,通过进一步的优化和重构,将能使系统更加稳定和易于维护。后续可考虑结合用户反馈进行增强,以作出更贴合用户需求的调整。

题目集八

一、功能设计

程序的功能设计围绕电器控制与状态管理展开,具体包括以下几个部分:

  1. 电器类型管理:通过类的继承实现对不同电器类型的管理(如开关、风扇、灯泡等),每类电器都有特定的行为和属性。
  2. 命令输入与解析:用户输入以特定格式定义电器及其连接方式,通过正则表达式解析命令。
  3. 状态更新与计算:根据用户的命令更新电器的操作状态,计算电压和电流,确保程序能反映真实电器的工作状态。
  4. 结果输出:以一致和清晰的格式向用户展示每个电器的状态信息,便于用户理解。

二、代码结构分析

  1. 类设计

    • Electric 类是所有电器类的基类,定义了电器的基本属性和方法。
    class Electric {
        public String s; // 类型
        public String id; // 类型ID
        public double shuV = 220; // 默认电压
        public String ofopen = "turned on"; // 开关闭合状态
        public int speed = 0; // 风扇速度
        public double lin = 0.00; // 连续类型的参数
        public int resistance; // 电阻值
    
        public Electric(String s, String id) {
            this.s = s;
            this.id = id;
        }
    
        public void display() {}
        public void regulate(String vs) {}
        public void reshuV(double shuop) {}
    }
    
    • 各子类继承并实现了具体的displayreshuV方法。
  2. 方法实现分析

    • Kaiguan(开关)的reshuV方法控制开关状态对电压的影响:
    public void reshuV(double shuop) {
        if (ofopen.equals("turned on")) {
            shuV = 0; // 如果开关打开,电压为0
        } else if (ofopen.equals("closed")) {
            shuV = shuop; // 根据条件设置电压
        }
    }
    
    • Fendang(风扇)类中调节风速的实现:
    public void regulate(String vs) {
        if (vs.equals("+") && speed < 3) {
            speed++; // 增加风速
        } else if (vs.equals("-") && speed > 0) {
            speed--; // 降低风速
        }
    }
    
  3. 输入解析

    • 用户输入以多行形式获取,通过正则表达式解析并存储连接关系:
    if (s.startsWith("#T")) {
        Pattern pattern = Pattern.compile("#(.*):(.*)");
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            chuanxu = String.valueOf(matcher.group(1));
            pop = String.valueOf(matcher.group(2));
        }
        connection.add(chuanxu + ":" + pop); // 将解析的线路存入连接列表
    }
    

三、时间复杂度

  • 输入解析:O(n) 由于逐行读取和解析输入的复杂度与输入行数成正比。
  • 状态更新:O(m) 在更新电器状态时,可能需要遍历与当前命令相关的电器集合。
  • 电流和电压计算:在计算电压和电流状态时,需要遍历所有电器的集合,时间复杂度为 O(e),其中 e 是电器的数量。

总体时间复杂度为 O(n + m + e)。

四、空间复杂度

  • 使用 HashMap 和 ArrayList 来存储电器的状态和连接关系,空间复杂度为 O(e + n),其中 e 表示电器数量,n 表示输入的总行数。

五、圈复杂度

圈复杂度受控于非平坦的控制结构,主要体现在:

  • 条件分支的嵌套,例如电器类型的比较和状态更新操作:

    for (Entry<String, Map<String, Electric>> entry : maps.entrySet()) {
        if (sid.startsWith("K")) {
            // ...
        } else if (sid.startsWith("F")) {
            // ...
        }
        // 更多条件分支...
    }
    
  • 对于每种电器的状态更新或计算,可能存在深层嵌套的循环与条件判断,导致圈复杂度较高。

六、详细代码分析

  1. 电器类的继承与实现

    • 各类电器采用多态,通过重写display()reshuV()实现特有的行为:
    class Baichi extends Electric {
        public void display() {
            int a = 0;
            // 根据电压计算亮度
            if (shuV >= 0 && shuV <= 9) {
                a = 0;
            } else if (shuV >= 10 && shuV <= 219) {
                a = (int) ((5 * shuV) / 7 + 43);
            } else if (shuV == 220) {
                a = 200;
            }
            System.out.printf("@B%s:%d\n", id, a);
        }
    }
    
    • 风扇类通过调节速度影响电压输出:
    public void regulate(String vs) {
        if (vs.equals("+") && speed < 3) {
            speed++;
        } else if (vs.equals("-") && speed > 0) {
            speed--;
        }
    }
    
    public void reshuV(double shuop) {
        shuV = speed * 0.3 * shuop; // 设备电压的计算
    }
    
  2. 输入读取与命令解析

    • 使用正则表达式解析并跟踪电器连接关系。关键部分在于判断处理各个类型的命令:
    if (s.startsWith("#M")) {
        Pattern pattern = Pattern.compile("#(.*):(.*)");
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            bingxu = String.valueOf(matcher.group(1));
            pop = String.valueOf(matcher.group(2));
        }
        connection1.add(bingxu + " " + pop); // 记录并联电路
    }
    

以下是题目八的类图,展示了我的代码是如何设计类以及方法的使用:

再是我的顺序图在这个顺序图中,我们展示了以下步骤:

七、踩坑心得

  1. 正则表达式使用

    • 当使用正则表达式解析输入时,处理不当可能导致出错。例如,输入格式错误时,该部分没有有效的错误提示,容易导致后续逻辑失效。
  2. 状态逻辑复杂

    • 在状态更新时对多个电器的状态判断逻辑复杂,若条件较多,很容易出错。对于电器的状态更新应优先考虑单一功能模块化设计,减少循环和条件嵌套。
  3. 电流计算涉及多个类

    • 各电器类别的电流计算涉及多个类之间的交互,这增加了理解的复杂度。在设计时若电器较多,应提前考虑电压和电流计算的关系。

八、改进措施

  1. 增加输入验证

    • 对输入格式进行验证,避免由于用户输入不当导致的程序异常。使用 try-catch 捕获异常,并给出用户友好的提示信息。
  2. 分离逻辑

    • 将复杂的逻辑部分拆分为独立的方法,并添加注释。这将有助于提高代码可读性,降低维护成本。
    public void checkElectricState(String sid) {
        // 状态检查逻辑
    }
    
  3. 引入设计模式

    • 考虑应用策略模式或状态模式,根据电器类型不同选择合适的电压和电流计算方式,减少条件分支的数量,提高可维护性。

九、收获与不足

收获

  • 深入理解了Java中的面向对象编程(OOP)原则与电器状态管理的实现,掌握了多态和继承的具体应用。
  • 学会了使用正则表达式解析命令输入,提高了对字符串处理的能力。

不足

  • 逻辑复杂性高,代码可读性较差,需考虑重新设计代码结构以增强可维护性。
  • 程序对错误输入的鲁棒性不足,缺乏必要的异常处理,导致系统易崩溃。

结论

该电器控制系统展示了良好的设计思路和实现方法,通过继续优化输入处理、逻辑简化和错误管理,该程序可以更好地满足用户需求并增强可用性与稳定性。未来的发展方向可以进一步深入 OOP 的实际应用,提高程序的灵活性与扩展性。

总结

一、迭代与演进过程的总结

第一次迭代:基础系统构建与简单功能实现

在首次迭代中,程序实现了一个基础的电器控制系统,包含了基本的电器类型和简单的功能,如开关的基本状态、灯泡的亮度、风扇的速度等。总体设计清晰,具有良好的模块化。

经验与问题

  • 模块化设计:通过继承Electric类定义不同类型的电器,成功实现了代码复用。
  • 缺乏输入验证:用户的输入未经过严格的检查,容易导致系统崩溃或逻辑错误。例如,输入格式错误会导致程序无法正常执行,未能提供有效的反馈给用户。

反思

  • 首次迭代提醒我们,代码实现功能的同时,也必须考虑用户输入的多样性和不确定性。系统应具备更好的健壮性来处理意外输入,确保用户的错误能得到恰当处理,而不会使系统崩溃。

第二次迭代:功能扩展与复杂性增加

在第二次迭代中,程序进行了增强,支持多种电器的管理,比如增加了多个试卷和分数的处理逻辑,以及对电器状态的动态管理。嵌入的逻辑更复杂,功能更加贴近实际应用需求。

经验与问题

  • 功能扩展:系统引入了多试卷管理功能,使其更贴合实际应用场景。同时,增加了对分数的管理,即为每一个电器增加了分数的计算。
  • 输入错位问题:尽管进行了一定的输入校验,但用户在输入时,若顺序不对或者漏掉某个编号,可能会导致判题过程中的错误,错位输入依然是一个隐患。

反思

  • 第二次迭代强调了在实现功能扩展时,必须同时考虑到输入的灵活性和准确性。虽然增加了格式检查机制,但对于输入顺序的错误不够敏感。引入更严格的检查方法(如 isValidInput() 函数)是必要的,但仍需实现更智能的解决方案来减少用户失误引发的问题。

二、综合反思与总结

  1. 健壮性与用户体验

    • 代码的健壮性至关重要。用户输入的错误应该不会导致系统崩溃,而是能够提供指导性反馈。第一次迭代中的问题促使我们重视输入验证和错误处理。
  2. 模块化设计与扩展性

    • 模块化设计使得系统在功能扩展时更具灵活性。随着电器种类的增加,良好的模块化能够提高可读性、可维护性与复用性。
  3. 错误与异常处理

    • 提高代码的鲁棒性是从单一功能扩展到复杂流程所必须关注的。通过逐步引入用户反馈机制的完善,系统对于输入错误时不仅应能自我修复,更需提供反馈,帮助用户“纠正错误”。
  4. 动态管理能力

    • 动态性是电器控制系统提高实用性的关键。在第二次迭代中实现的优化(如标记删除),结合信息状态管理,显示了有效的数据管理对整个系统的重要性。

三、未来优化与提升方向

  1. 实现更复杂的电器管理功能:当前系统仍只支持简单的电器类型扩展,未来可通过接口或抽象类来引入更多电器或功能模块,如支持不同类型的电器组合及管理。

  2. 性能优化与数据存储:面对大量电器数据,逐渐引入持久化数据存储机制(如使用数据库)将提升性能和数据查询速度。

  3. 用户界面改进

    • 考虑为系统引入图形用户界面(GUI),使用户操作过程更加友好直观,并以视觉化方式展示电器状态和管理功能。

最终总结

通过这两次迭代的开发过程,我获得了对编程系统性设计、代码架构优化、输入错误处理和复杂功能实现等多方面的综合理解。每次迭代都让我在思维上有了新的升华,从最初的简单实现逐步过渡到复杂场景处理的全面能力。今后,我将继续关注系统的健壮性、可维护性和可扩展性,力求在实际开发中产出更加高效和稳定的软件成果。

posted @ 2024-12-28 18:16  王郅坚  阅读(42)  评论(0)    收藏  举报