串口助手开发经验

Posted on 2025-09-24 22:28  Luis-123-long  阅读(9)  评论(0)    收藏  举报

1.在开发log功能的时候,发现点击发送数据后,没有反应(初始化陷阱)

经检查(很漫长的检查)后发现在最后面加了上次遗留的初始化导致的,相当于初始化两次,

img

因为加了log功能后需要传入两个实例的构造函数,但是在最后面又重新进入初始化了,但是没有传入参数,导致_logger为null。

后续debug引入一个日志验证

img

发现一初始化就为null,后续要注意这个

  • 先初始化基础服务(如日志器)
  • 再初始化依赖它们的服务

2.空对象模式应用

在使用log记录的时候,设计模式特别适合像空日志器这样的"无状态工具对象",它提供了接口实现的灵活性,同时保持了资源使用的最优化

NullSerialPortLogger中使用私有构造函数是为了:

  1. 强制单例模式:确保全局只有一个实例
  2. 防止误用:避免开发者创建不必要的实例
  3. 优化资源:减少内存占用和初始化开销
  4. 保持一致性:所有使用者共享相同的行为

img

单例模式在日志系统中的优势:

1.内存效率

// 使用单例:整个应用只有一个实例
var logger1 = NullSerialPortLogger.Instance;
var logger2 = NullSerialPortLogger.Instance;

// logger1 == logger2,内存中只有一个对象

2.简化访问

// 任何地方都可以直接访问
public class MyService
{
    private ISerialPortLogger _logger = NullSerialPortLogger.Instance;
    
    // 不需要构造函数注入
}

3.空对象模式

// 作为空对象模式的实现
public class SerialPortService
{public SerialPortService(ISerialPortLogger logger = null)
    {// 如果没有提供日志器,使用空日志器单例
        _logger = logger ?? NullSerialPortLogger.Instance;
    }
}

3.构造函数设计原则

  • 所有必需依赖都应作为参数
  • 使用参数验证确保依赖不为null
  • 避免在构造函数中执行复杂逻辑

实现依赖注入

img

实现定时发送

ISerialPortService 的实现类 SerialPortService 包含定时发送、异常处理等逻辑。通过接口抽象,FrmHelper 可以:

• 调用 SendData 和 StartTimedSend 方法时,无需关心具体实现细节。

• 在需要时替换为其他实现(如带日志或性能监控的版本)。

总结

这种写法的核心目的是 解耦 和 提高扩展性,符合以下设计原则:

  1. ​ 依赖倒置原则(DIP):依赖抽象(接口),不依赖具体类。
  2. ​ 开闭原则(OCP):通过扩展而非修改实现功能变化。
  3. ​ 单一职责原则(SRP):FrmHelper 专注于界面逻辑,不处理串口细节。

github地址:luis1900/SerialPortAssistant-OOP

gittee地址:https://gitee.com/beethoven1900/serial-port-assistant

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3