如何合理地实现类结构

本文关键字:实现 结构 | 更新日期: 2023-09-27 18:32:30

我希望我的问题合法,因为我并不真正习惯所有的分层类结构。

我尝试封装一个类,该类为连接到设备的两个不同相机提供相同的功能。这些函数被认为是在类 DeviceObject 中,而我想通过使用 Camera1Camera2 的实例来访问这些函数。下面是一些可能不起作用的伪代码:

public class Camera1 : DeviceObject
{
    public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM1;
}
public class Camera2 : DeviceObject
{
    public Generic.CameraSelect Camera { get; set; } = Generic.CameraSelect.CAM2;
}
public class DeviceObject
{ 
    public void SomeFunction() 
    {
        HardwareDriver.Function(SelectedCamera);     
    }
}

我想要的是轻松访问依赖于相机类的设备对象的方法:

public void Method() 
{
    Camera1 Cam1 = New Camera1();
    Camera2 Cam2 = New Camera2();
    Cam1.SomeFunction();
    Cam2.SomeFunction();
}

如果这是一个愚蠢的问题,我深表歉意,但经过 7 个小时的编程,我完全陷入困境,不再脑海中:)

更新:

我已经实现了 - 正如你们所有人所建议的那样 - 一个抽象基类,并将相机对象派生为基类的成员。

到目前为止我还不知道的是,可以将派生类强制转换为基类的类型。这对我来说绝对是新的,但帮助了我一个战利品!与我的实施。

因此,感谢所有帮助我的人,没有让我下地狱:)

如何合理地实现类结构

为什么不使用抽象类?

public class Camera1 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}
public class Camera2 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}
public abstract class Camera
{
    public abstract Generic.CameraSelect CameraType { get; set; }
    public void SomeFunction()
    {
        HardwareDriver.Function(this);
    }
}

通常仅在需要不同的实现(方法(时才使用继承。 如果两个相机的实现相同,但涉及的数据不同,则可以使用一个类和一个工厂来"创建"具有适当设置的相机。

public class CameraFactory
{
    public static Camera1 {
    get {
        return new Camera {Camera = Generic.CameraSelect.CAM1};
    }
    public static Camera2 {
    get {
        return new Camera {Camera = Generic.CameraSelect.CAM2};
    }
}

这不是唯一的方法,但这是一种方法。

另请注意,如果 Camera 属性不应更改,则使其仅get(或者最坏的情况是使用私有资源库(。

正如其他人所建议的那样,您的问题的答案可能是添加一个抽象/覆盖:

public class Camera1 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM1";
}
public class Camera2 : Camera
{
    public override Generic.CameraSelect CameraType { get; set; } = "CAM2";
}
public abstract class Camera
{
    public abstract Generic.CameraSelect CameraType { get; set; }
    public void SomeFunction()
    {
        HardwareDriver.Function(this);
    }
}

但是,我被HardwareDriver类触发了。我想在这里说两点:

  1. 驱动程序处理功能,而不是名称。如果你的目标是分解,你可能想去一个双重调度,根据范围调用东西。
  2. 相机的目的是什么,为什么它以"世界"的运作方式建模?

双重调度

让我们从双重调度开始。在我看来,你最终可能会在某个地方得到一个包含逻辑的大型"开关"块。这对我来说没有多大意义。基本上,您可能会尝试将对象与逻辑分离 - 因此让我们使用继承来执行此操作。在这种情况下,它将像这样工作:

public class Camera1 : Camera
{
    public override void SomeFunction(IDeviceVisitor driver)
    {
        // Very simple camera:
        driver.HandleAngle(this, 12.0);
        driver.GenerateModel();
    }
}
public class Camera2 : Camera
{
    public override void SomeFunction(IDeviceVisitor driver)
    {
        // This camera understands focus
        driver.HandleAngle(this, 12.0);
        driver.HandleFocus(this, focus, this.focus * 1.2); 
        driver.GenerateModel();
    }   
}
public class SomeHardwareDriver : IDeviceVisitor { ... } 
public interface IDeviceVisitor
{
    void HandleFocus(Camera camera, double focusValue, double realDistance);
    void HandleAngle(Camera camera, double angle);
    void GenerateModel();
    // [...]
    // etc
}
public abstract class Camera
{
    public abstract void SomeFunction(IDeviceVisitor driver);
}

我传递this的原因是因为您可能想从HardwareDriver中调用另一个相机函数来执行魔术。

世界运作方式建模

如果两个相机彼此没有任何共同点,请不要为它们提供共同的基类。这毫无意义。

或者更一般的规则:永远记住,类模型不需要对你这个人有意义;它必须对计算机有意义。

如何知道你什么时候跑错了路

2条线索:

  • 如果你最终得到了大的开关块,很多if-then-else的,等等 - 那么你可能做错了。
  • 如果复制粘贴代码,则可能做错了。

你可以有一个封装方法,它接受DeviceObject参数,如

public void CallSomeFunction(DeviceObject dobj) 
{
    dobj.SomeFunction();     
}

然后,您可以创建任何相机基类型的实例并调用该方法

Camera1 Cam1 = New Camera1();
CallSomeFunction(cam1);