是否有可以帮助我存储对象"capabilities"的设计模式?



我正在开发一个 C# 程序,该程序允许用户通过 TCP telnet 样式连接与各种视音频设备(如接收器和切换器)进行交互和配置(根据各种设备制造商的命令集)。我使用命令模式来封装命令。应用一次只能与一个设备交互,因此当它连接时,它会枚举设备并创建 DeviceVersion 对象。此对象存储所有设备通用的某些属性。它还需要维护每个设备的功能列表。例如,某些设备没有音量控制。其他人这样做,但没有能力更改输入设备。我讨厌在每个 DeviceVersion 对象中存储一长串布尔值的想法。我想我应该有一个类似 CapabilityContract 的对象,它封装了一个字典,例如 Dictionary,它可以将功能名称映射到布尔值。至少这样,我可以放入一个 ContractFactory 或可以通过文本配置文件或其他方法动态生成这些功能对象的东西。

但是,在解析命令输出时,在某些情况下,允许的功能可能会更改响应的解析方式。例如,可以在输出上分离音频和视频的 AV 开关可能具有 GetInput 命令,该命令返回有序对,例如(音频输入、视频输入),但是,在音频和视频始终链接的设备上,它可能只返回(输入)。命令解析器接口实现维护对 DeviceVersion 的引用,因此它可以查找功能,但这会导致相当多的 if 语句或 switch 语句。我考虑过为每个 DeviceVersion 类型生成不同的解析器实现的想法,但这会导致大量重复的代码。我是否缺少一些设计模式可以为我简化这个问题并避免大量维护布尔值或大量重复代码?

目前尚不清楚DeviceVersion class的目的是什么,也许DeviceInfo更好地描述了它。我的建议是使用IDeviceAbility集合,其中每个项目代表一种功能,例如IPlayable。通过这种方式,您可以附加/分离、获取信息、启用/禁用以及对所有功能执行其他操作,但所有特定功能只有一个实现。尽管您仍然可以覆盖它们。

这样做的另一个好处是,您可以分别测试和模拟 DeviceInfo 类的每个功能。 DeviceCapability 中的更改不会影响 DeviceInfo 和所有 DeviceCapability 实现。

如果要解决这个问题,我会使用工厂模式,也是在 MSDN 上,我定义了一个基本接口(无实现)或抽象类(包含一些实现),然后是一个工厂来检索这些对象。

这样,您的系统就有一个通用的实现来与这些设备通信,并且您不会复制代码,因为您只是继承基类来为您可能与之交互的每个设备创建实现。我建议你使DeviceVersion对象更通用一点,并将其转换为基类。您可以将命令模式实现包装到工厂模式中,这应该可以帮助您实现目标。

不久前,我使用此模式来实现一个 C# 应用程序,该应用程序允许您使用四种不同的 SDK 在四种不同类型的 DVR 之间切换。

这是一个快速而肮脏的例子:

设备类型枚举:

public enum DeviceType {
  Receiver,
  Switcher
  // etc
}

基类:

public interface DeviceVersion {
  // What type is this?
  DeviceType DeviceType { get; }
  // Common Properties and Methods, etc here
  #region Function Availability Properties
  bool CanFastForward { get; }
  bool CanPlay { get; }
  bool CanStop { get; }
  bool Can... { get; }
  ...
  #endregion
  #region Methods
  bool Connect(string ipAddress, string user, string password);
  void Disconnect();
  void Play();
  void Stop();
  ...
  #endregion
}

切换台类:

public class Switcher : DeviceVersion {
  // Override the virtual
  public DeviceType DeviceType { get { return DeviceType.Switcher; } }
  public bool CanPlay
  {
      get { return true; }
  }
  ...
}

工厂等级:

public class DeviceFactory {
  // This is the factory method
  public static DeviceVersion GetDevice(DeviceType type) {
    switch (type) {
      case DeviceType.Switcher:
        return new Switcher();
      case DeviceType.Receiver:
        ...
      default:
        ...
    }
  }
}

然后在连接到其他设备的主要方法中,您将执行以下操作:

...
var currentDeviceType = DeviceTypes.Switcher;
...
var device = DeviceFactory.GetDevice(currentDeviceType);
if (device.Connect("1.2.3.4", "user", "pass")) {
  if (device.CanPlay)
    device.Play();
  ...
}
...

至于协定和功能,您可以在基类中实现字典或类似内容来保存这些项目,因为基类中的所有内容都由从它继承的类继承。

最新更新