我正在开发一个C#程序,允许用户通过TCP telnet样式连接(根据各种设备制造商的命令集)与各种AV设备(如接收器和切换器)进行交互和配置。我使用命令模式来封装命令。该应用程序一次只能与一个设备进行交互,因此在连接时它会枚举设备并创建一个DeviceVersion对象。此对象存储所有设备共有的某些属性。它还需要维护每个设备的功能列表。例如,某些设备没有音量控制。其他人这样做,但没有能力改变输入设备。我讨厌在每个DeviceVersion对象中存储一长串布尔值的想法。我想我应该有类似CapabilityContract对象的东西,它封装了一个字典,如Dictionary,它可以将功能名称映射到布尔值。至少我可以通过文本配置文件或其他方法放入ContractFactory或可以动态生成这些功能对象的东西。
但是,在解析命令输出时,在某些情况下,允许的功能可能会更改解析响应的方式。例如,可以在输出上分离音频和视频的AV开关可以具有GetInput命令,该命令返回类似(音频输入,视频输入)的有序对,但是,在音频和视频总是链接的设备上它可以返回(输入)。命令解析器接口实现维护一个返回DeviceVersion的引用,因此它可以查找功能,但这会导致相当多的if语句或switch语句。我玩弄了为每个DeviceVersion类型生成不同解析器实现的想法,但这将导致大量重复的代码。是否有一些我缺少的设计模式可以为我简化这个问题并避免大量维护布尔值或大量重复代码?
答案 0 :(得分:1)
目前还不清楚DeviceVersion类的目标是什么,也许DeviceInfo更好地描述了它。我的建议是使用IDeviceCapability集合,其中每个项目代表一个功能,如IPlayable。通过这种方式,您可以附加/分离,获取信息,启用/禁用以及使用所有功能执行其他操作,但只有一个实现所有特定功能。虽然你无论如何都可以覆盖它们。
另一个好处是你可以分别测试和模拟DeviceInfo类的每个功能。 DeviceCapability中的更改不会影响DeviceInfo和所有DeviceCapability实现。
答案 1 :(得分:0)
如果我要解决这个问题,我会选择Factory Pattern,也可以MSDN,我在那里定义了基本接口(没有实现)或抽象类(包含一些实现),然后是工厂检索这些对象。
通过这种方式,您可以使用系统与这些设备进行通信的通用实现,并且您不会复制代码,因为您只是继承基类来为可能与之交互的每个设备创建实现。我建议你让你的DeviceVersion对象更通用,然后将其转换为基类。您可以将命令模式实现包装到工厂模式中,这应该可以帮助您实现目标。
我前一段时间使用这种模式来实现一个C#应用程序,它允许您使用四种不同的SDK在四种不同类型的DVR之间切换。
这是一个快速而又肮脏的例子:
DeviceType Enum:
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();
...
}
...
至于契约和功能,你可以在基类中实现一个字典或类似的东西来保存这些项,因为基类中的所有内容都是从继承它的类继承的。