把类本身看作设备。这里的主要好处是能够重用一次编写的代码—例如,您的所有设备都有地址,它们可以连接、测试连接、断开连接—为什么不在一个抽象的“设备”类中使用这些代码,并使所有设备从中继承?
public class DeviceTesting
{
private string powerSupplyAddress = "DA5";
private string dataLoggerAddress = "DA6";
public static void main()
{
//bring interface into life
DeviceInterface interface = GPIBInterface(); //example of inheritance - GPIB could be just one of the many device interfaces
//the constructor in PowerSupply takes on the responsibility of initializing itself
PowerSupply ps = new PowerSupply(powerSupplyAddress, interface); //plugged in with interface - has a reference to it
//you could have multiple types of data loggers - all could inherit from DataLogger, and here so does HP34970
//This means you can reuse the common code for data loggers, and write only the specifics for each specific device of that kind
DataLogger myLogger = new HP34970(dataLoggerAddress, interface);
//now, do whatever you do with the real devices
ps.SetVoltage(220); //send voltage command directly
interface.SendLogMessage("Interface is operational");
interface.ExecuteTest("test1"); //send voltage command through interface
//etc... you get the idea...
}
}
现在,由于接口拥有与之接口的设备的知识,它必须在其构造函数中包含这些设备(在面向对象设计中,也称为依赖项注入,更具体地说,这里是构造函数注入):
public GPIBInterface : DeviceInterface //here we are reusing code that's same for all interfaces
{
//whoever attaches to this interface is responsible for registering itself with it
public PowerSupply Power{get;set;}
public DataLogger Logger{get;set;}
//notice here that it can work with any class that inherits from DataLogger
public GPIBInterface()
{
}
private override void TestInitialization() //as an example, we write our own testing by overriding some method in base class
{
base.TestInitialization(); //make sure that the base class checks it's ok - e.g. if it's own display is working or similar...
if (Power.TestConnection() == false)
throw new DeviceNotWorkingException(ps);
if (Logger.TestConnection() == false)
throw new DeviceNotWorkingException(_logger);
}
public void SendLogMessage(string message)
{
Logger.SendMessage(message);
}
public void ExecuteTest(string testName)
{
switch(testName)
{
case "test1":
Power.SetVoltage(280);
Logger.SendMessage("Voltage increased to 280V");
break;
}
}
}
基本上,如果你的设备在“现实生活”中相互作用,那就意味着它们应该有一个相互连接的设备的引用。例如,如果您将PowerSupply直接插入到logger,那么PowerSupply类应该有对logger的引用。但是,如果它连接到接口,然后再连接到记录器,那么电源必须只引用接口而不是记录器(因为它没有连接到它)。
当你掌握了这一点,你的程序将真正受益于某种控制反转(IoC)模式——这样你就可以在一开始就定义什么是记录器,什么是电源,谁是显示器,什么时候有人需要某个特定的设备,IoC容器就会提供它。这样你就不必每次城里有新设备的时候都重写代码——只要用IoC容器注册新类型,一切就都正常了。