我使用enum
来标记两种不同类别的产品 - SensorDevice和[data] CaptureDevice。
它们旨在用于物理上相互插入,但并非每个接收器模型都可以使用每个传感器模型,因此我为不同的平台创建了一个Enum,因此GUI只显示给定设备的兼容附件: / p>
enum Platform {
Standard,
Deluxe,
Jumbo
}
abstract class CaptureDevice
{
public Platform platform;
public bool IsCompatibleWith(SensorDevice sd)
{
return sd.Platforms.Contains(this.Platform); // <- this is type-checking!
}
}
abstract class SensorDevice
{
public IEnumerable<Platform> Platforms;
public bool IsCompatibleWith(CaptureDevice cd)
{
return this.Platforms.Contains(cd.Platform); // <- this is type-checking!
}
}
我开始觉得这很臭,因为枚举是硬编码的。我正在考虑使用“通过多态性替换类型代码”重构,但我不太确定如何为这种情况做这件事。有什么建议吗?
答案 0 :(得分:1)
你可以做以下事情来摆脱枚举。
用类替换枚举。
public abstract class Platform {}
添加Device
类,如果它与Platform
兼容,则会回答。
public abstract class Device
{
public abstract bool IsCompatibleWith(Platform platform);
}
使CaptureDevice
成为Device
的子类。
public abstract class CaptureDevice : Device
{
public Platform Platform;
public override bool IsCompatibleWith(Platform platform)
{
// I'm using type comparison for the sake of simplicity,
// but you can implement different business rules in here.
return this.Platform.GetType() == platform.GetType();
}
public bool IsCompatibleWith(SensorDevice sd)
{
// We are compatible if sensor is compatible with my platform.
return sd.IsCompatibleWith(this.Platform);
}
}
使SensorDevice
成为Device
的子类。
public abstract class SensorDevice : Device
{
public IEnumerable<Platform> Platforms;
public override bool IsCompatibleWith(Platform platform)
{
// I'm using type comparison again.
return this.Platforms.Any(p => p.GetType() == platform.GetType());
}
public bool IsCompatibleWith(CaptureDevice cd)
{
// We are compatible if capture is compatible with one of my platforms.
return this.Platforms.Any(p => cd.IsCompatibleWith(p));
}
}
基本上,这就是你需要做的。为了说明它是如何工作的,我在下面添加了代码。
// Platforms
public class StandardPlatform : Platform { }
public class DeluxPlatform : Platform { }
public class JumboPlatform : Platform { }
// Capture device(s)
public class CD1 : CaptureDevice
{
public CD1()
{
Platform = new StandardPlatform();
}
}
// Sensor device(s)
public class SD1 : SensorDevice
{
public SD1()
{
Platforms = new List<Platform>
{
new StandardPlatform(),
new DeluxPlatform()
};
}
}
public class SD2 : SensorDevice
{
public SD2()
{
Platforms = new List<Platform> {new JumboPlatform()};
}
}
// Somewhere in the code...
var cd1 = new CD1();
var sd1 = new SD1();
Console.WriteLine(cd1.IsCompatibleWith(sd1)); // True
Console.WriteLine(sd1.IsCompatibleWith(cd1)); // True
var sd2 = new SD2();
Console.WriteLine(sd2.IsCompatibleWith(cd1)); // False
Console.WriteLine(cd1.IsCompatibleWith(sd2)); // False
答案 1 :(得分:0)
编辑:如果你想摆脱枚举,为什么不能使用配置文件?
您可以像这样配置您的平台:
<Platforms>
<Platform name="Standard">
<Device>Namespace.of.your.Device.CaptureDevice</Device>
<Device>Namespace.of.another.Device.AnotherDevice</Device>
</Platform>
<Platform name="Deluxe">
<Device>Namespace.of.your.Device.CaptureDevice</Device>
</Platform>
</Platforms>
其他语法:
<Platforms>
<Platform>
<Name>Standard</Name>
<Devices>
<Device>Namespace.of.your.Device.CaptureDevice</Device>
<Device>Namespace.of.another.Device.AnotherDevice</Device>
<Devices>
</Platform>
</Platforms>
然后,你有相同的基础结构,你可以做这样的事情:
abstract class ADevice<T> where T : ADevice<T>
{
public ADevice<T>(T device , string filename)
{
// Parsing of the file
// Plus, setting the Platforms Property
}
// Or (but you should keep the first constructor to see the filename dependency)
public ADevice<T>(T device)
{
// Parsing of the file
}
public IEnumerable<Platform> Platforms { get; private set; }
public bool IsCompatibleWith(T device)
{
return this.Platforms.Contains(device.Platform); // <- this is type-checking!
}
}
然后:
abstract class CaptureDevice : ADevice<CaptureDevice>
{
public CaptureDevice(CaptureDevice device, string filename)
: base(device, filename)
{
}
// Or (But still same comment)
public CaptureDevice(CaptureDevice device)
: base(device, defaultFilename)
{
}
}
SensorDevice
而不是Enum
,您可以创建一个简单的类:
public class Platform
{
public Platform(string name)
{
Name = name;
}
public string Name { get; }
}