我在 Java 中遇到一种情况,我有一个外部设备,我想通过串行 I/O 进行通信。我知道如何做到这一点,但我现在处于重构模式,以确保我有一个可维护的软件包,并且正在寻求关于在高级别上做什么/不做什么的建议(具体问题如下)
从概念上讲,假设我有一个低级 DeviceIOChannel
接口(interface),其中包含多种方法(getInputStream、getOutputStream 以及其他一些用于控制连接/断开检测等的方法),由一个或多个处理各种数据链路类型(RS232、TCPIP 等)的 I/O 的类实现。我的一些软件,让我们称之为 Device
类,专门用于管理 I/O(解析输入、构造输出、管理低级状态机),但不知道 DeviceIOChannel
如何执行其操作的详细信息(因此我可以将它与 RS232 或 TCPIP 一起使用,而无需更改 Device
类)。因此,我可能会将 DeviceIOChannel
作为参数传递给 Device
的构造函数。我还想向外界公开某种数据模型。
- 我对
DeviceIOChannel
/Device
的分区听起来正确吗? Device
需要在工作线程上主动执行一些操作。设置此功能的最佳方法是什么?我应该让它创建和管理自己的Thread
或ScheduledExecutorService
吗?或者我应该传入ScheduledExecutorService
作为构造参数?- 关于如何确定
Device
类是否应该具有与构造不同的startup()
方法,有什么想法(最好能链接到网络上的好文章!)? (在构造中进行所有初始化让我感到紧张......似乎类实例构造应该很快,然后应该为稍后的初始化或启动阶段保留冗长的内容。) - 是否有一个具有一对关闭/重新启动方法的
Device
类,而不是不关闭 + 需要创建一个新的Device
实例? - 我对 MVC 架构还很陌生:创建
Device
实现的DeviceDataModel
接口(interface)是否有意义,或者我应该有一些单独的类DeviceDataModel
以某种方式与Device
类进行双向通信吗?
最佳答案
一次一点地回答您的问题。
- 是的,听起来确实很合理。
- 是的,为你的线程传递一个抽象肯定会让类更加可测试。构造函数中的两个依赖项听起来并非不合理。
- 拥有启动方法会增加更多开销(在方法调用上,您必须检查启动是否被调用,您不能假设它),但是我同意构造函数上的此类网络 Activity 在我看到它时总是看起来很奇怪。我认为这确实是一个风格问题,但单独方法的一个优点是,如果您需要在开始之前调试或记录状态,您的 Device 类可以将其配置表示为实例,而不是让其他东西无法获取该对象的句柄。
- 我认为这个问题的答案几乎完全取决于你如何处理#3。一个毫无意外的 API,如果在其构造函数中启动,则无法重新启动,而如果通过方法启动,则有办法重新启动。
- 考虑到此类的网络 IO 性质,DeviceDataModel 接口(interface)将使其余代码更易于测试。但是,它不需要直接由 Device 类实现,而是作为内部类从 Device 类的方法返回,因此它可以轻松地与设备类通信,但仍然可以在测试过程中进行模拟或 stub 。至少,只要 DeviceDataModel 的序列化不是必需的。
关于java:重构案例(MVC的M和C?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2156783/