Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否有一种设计模式可以帮助我存储对象;能力;?_C#_Design Patterns - Fatal编程技术网

C# 是否有一种设计模式可以帮助我存储对象;能力;?

C# 是否有一种设计模式可以帮助我存储对象;能力;?,c#,design-patterns,C#,Design Patterns,我正在开发一个C#程序,该程序允许用户通过TCP telnet类型的连接(根据各种设备制造商的命令集)与各种AV设备进行交互和配置,如接收器和交换机。我使用命令模式来封装命令。应用程序一次只能与一个设备交互,因此当它连接时,它会枚举设备并创建DeviceVersion对象。此对象存储所有设备共有的某些属性。它还需要维护每个设备的功能列表。例如,某些设备没有音量控制。其他人有,但没有能力改变输入设备。我讨厌在每个DeviceVersion对象中存储一长串布尔值。我想我应该有一个类似Capabili

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


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

如果我要解决这个问题,我会使用一个,也就是说,我定义了一个基本接口(没有实现)或抽象类(包含一些实现)然后是一个工厂来检索这些对象

这样,您的系统就有了一个通用的实现来与这些设备进行通信,并且您不会复制代码,因为您只是继承了基类来为您可能与之接口的每个设备创建实现。我建议您让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();
  ...
}
...

至于契约和功能,您可以在基类中实现一个字典或类似工具来保存这些项,因为基类中的所有内容都是由继承自它的类继承的。

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


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

问题的关键在于,两台切换器可能具有不同的功能集。它们更像是组件,所以重写基类会变得非常混乱,因为在检查不同功能时,每个类中都会有大量重复的代码。我想构建我的功能列表,然后将其应用于DeviceVersion(已经由工厂方法创建)。我遇到的问题是,响应解析器和命令队列必须强制执行功能列表,我希望避免大量的if或switch语句。是的,这似乎是一个很难解决的问题。我在我的示例中添加了一些说明,说明我是如何处理与之接口的不同DVR的不同“功能”的。与我共事的SDK中没有一个是以同样的方式工作的。尝试处理这个完全不同的功能集也可以通过查看并查看是否有一种方法可以将您尝试执行的操作包装到一个可扩展的类结构中来解决。也许我可以将CommandQueue和ResponseParser对象作为一种实体组件模式,其中,实际的解析和执行函数本身就是组件。但这只是将所有特征集的检查转移到工厂,并不能消除它们。不过,这可能比每次执行命令时都检查它们更好?(虽然我不关心CPU或内存优化,因为这里的一切都非常轻量级)我只是觉得我看到了一些模式解决了这样的问题,但我只是画了个空白。不知道这是否有帮助,但可能也值得一看和模式。