【问题标题】:Safely reinitialising member objects安全地重新初始化成员对象
【发布时间】:2017-09-20 04:32:19
【问题描述】:

希望这是一个适当的问题,因为我知道它可能非常笼统,甚至非常主观。

我目前正在重构一个相机类。完成后,我将在服务类中重用整个摄像头,但我遇到了一些问题。

相机类本身是一个面向对象的包装器,围绕制造商提供的相机 API(以便可以互换使用多个相机实现)。从现在开始,我将把制造商的相机对象称为“CAM”。

我正在为当前的设计计划这个:

  • ICamera:包含获取图像的方法和属性以及 connect()/disconnect() 方法和连接/断开事件。
  • ISerialCamera:相机的扩展,添加了串行端口对象。
  • ISerialPort:包含读/写串口的方法。

ICamera 和 ISerialPort 实现都依赖于 CAM。此外,当建立连接时,会创建一个新的 CAM 实例。这就是我的问题所在:

  • 实例化一个 ICamera。
  • Camera.Connect();
  • 通知发生错误
  • ICamera 已断开连接。
  • 我再次连接相机(在内部生成一个新的 CAM 实例)。

现在用新的 CAM 实例重新实例化串行端口对象对我来说是不好的做法吗?我问是因为对于面向对象的设计来说,这似乎是一个不合逻辑的举动。

例如,有人可能会拿走我的串行相机对象并决定使用 ISerialPort 作为某个函数的参数(例如)。

如果我要重新实例化我的串行端口对象,那么它们对串行端口的本地引用现在无效,并且串行的客户端将更难以解决断开连接的问题。

虽然有些人可能认为这是可以接受的,但我宁愿让我的相机对象的使用尽可能直观和简单。在我的理想解决方案中,ISerialPort 引用将始终指向同一个实例,但串行端口将与新的 CAM 实例相关联。

我会考虑以下解决方案:

  1. 由于串行端口实现特定于相机实现,我可以在实现中添加一个附加方法,但 不是接口,例如ISerialPort.Reinitialise(CAM),然后 ICamera 实现将能够将其串行端口转换为实现类型 (CAMSerialPort),使其能够调用新的 Reinitialise() 方法。

  2. 彻底删除串口对象。 ISerialCamera 扩展了 ICamera,但 ISerialCamera 直接包含了读/写串口的方法,无需添加串口对象。这行得通,但我宁愿选择组合而不是继承的解决方案。如果可能的话,我想远离继承层次结构,我觉得这几乎促使我通过将更多功能直接绑定到单个对象来打破单一责任原则之类的东西。

这些可以解决问题,但我不确定它是否会被视为广告实践,我不喜欢内部转换只是为了访问方法的想法(但也许我只是有偏见)。

对于解决此问题的任何特定模式或对我的设计选择进行任何更改/添加的一些有用提示将不胜感激。

最后澄清一下,我需要客户端将使用的接口尽可能通用,绝对没有声明特定于某种相机实现类型以及它是内部(或缺少)API。

编辑:一些附加信息,使其更清晰。

  • 图像采集不需要串口(这就是我选择不支持串口的 ICamera 的原因)。
  • 串行端口是某些相机的一项功能,允许串行通信
  • 在我的用例中,摄像头是包含微处理器的更大硬件解决方案的一部分。串行端口在那里,所以我可以使用相机向微固件发送读/写串行(而不是在相机上实际操作)。

串行端口充当我的客户端计算机和运行在单独板上的固件之间的链接。

另外,CAM API 可能不提供断开连接通知,所以整个事情需要根据故障进行同步。我有一个定期轮询设备状态的串行监视器。

  • 当设备处于某些状态时,我想禁用采集。
  • 当串行读取失败时,我可以假设相机已断开连接。
  • 当设备状态已启用但在读取发生之前发生采集(或在采集期间发生读取)时,我需要处理断开连接和采集中止。

用例总结:

  • 获取图像(如果已启用并已连接)
  • 读/写串口到固件(如果连接了相机)

【问题讨论】:

    标签: c# oop interface architecture camera


    【解决方案1】:

    如果没有一些具体的代码示例和问题示例,我认为这真的很难回答,但从我在这里收集到的一些可能的架构替代方案中,我可能会使用。

    首先-我认为您很直觉-您可能不希望相机暴露ISerialPort界面。


    您可以让ICamera 指示相机的抽象,并且您始终要求用户指示将信号发送到哪个端口

    camera.TakePhoto(serialPort);
    

    您可以强制ICamera 要求连接串口

    camera.TakePhoto(); //throw  InvalidOperationException
    camera.Connect(serialPort);
    camera.TakePhoto(); //Ok
    

    我的偏好是将串行端口用作相机的工厂

    var camera = serialPort.Connect();
    

    您甚至可以将摄像头设置为 IDisposable - 如果您将界面重命名为 ICameraConnection,这将更直观。

    using(ICameraConnection camera = cameraPort.Connect()) {
        camera.TakePhoto();
    }
    

    这有点帮助。

    【讨论】:

    • 我喜欢拥有 CameraConnection 类型的想法,但我仍然无法协调。我遗漏了一些细节: - 相机本身纯粹用于采集。但是物理相机具有串行通信的能力。串行通讯需要摄像头。采集不需要串行通信。 - 相机将在多个地方(不是同时)用于非常不同的操作,例如拍摄图像以校准图像校正程序。 - 串口目的是读/写非摄像头固件,摄像头为链接提供串口。
    猜你喜欢
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多