我一直在努力思考课程。即使在阅读了几个网站和书籍之后,我仍然不觉得我真的“明白了”。
我正在处理的应用程序有一个子程序,它可以通过USB到GPIB接口控制几个不同的测试设备。
所以,我有:
Laptop USB - GPIB Interface Power Supply (Device Address 5) HP34970 Datalogger (Device Address 6)
在我的子设备中,我想打开GPIB设备,发送一些SCPI命令打开电源,再向HP34970发送一些以切换继电器或测量电压。
看起来很简单,我可以很容易地使一切工作在同一个模块中。但是,我认为为GPIB接口,电源和HP34970提供单独的类会更好。如果是这种情况,我可以很容易地在其他项目中重用代码。
这里是我无法获得心理模型的地方 - 如果我创建GPIB类的实例并且有一个方法来“打开”到GPIB总线的通道,我如何允许其他类中的方法(如电源)使用GPIB类中创建的开放通道?例如,电源类中设置电压的方法。
如果有人可以花几分钟时间发布伪代码和一些解释来说明我可以/应该如何组织这些,我将非常感谢您的帮助!
由于
答案 0 :(得分:1)
我怎样才能允许其他方法 类(如电源)使用 在GPIB中创建的开放通道 类?
一种方法是创建一个复合类,用于保存Power Supply类和GPIB类的实例(抱歉C#):
public class PowerSupplyGPIBController
{
// Members
GPIB gpib;
PowerSupply powerSupply;
// Constructor
public PowerSupplyGPIBController(GPIB myGPIB, PowerSupply myPowerSupply)
{
gpib = myGPIB;
powerSupply = myPowerSupply;
}
// Method
public void SendPowerSupplyVoltage()
{
GPIB.Send(myPowerSupply.Voltage);
}
}
基本上你需要在某处保存GPIB和PowerSupply对象,并在它们之间传递数据/消息。
答案 1 :(得分:1)
我建议PowerSupply,Datalogger等的构造函数都接受实际进行通信的GPIB类的实例。然后当有人调用MyPowersupply.SetVoltage时,PowerSupply.SetVoltage例程可以使用该GPIB对象发送适当的请求。如果你将拥有多个线程,你应该使用锁来确保通信不会受到攻击。我没有看到复合课程有多大好处。只需让每个PowerSupply,Datalogger等都拥有一个可用于与物理设备通信的GPIB类实例。
答案 2 :(得分:1)
将类视为设备本身。这里的主要好处是能够重用一次编写的代码 - 例如,您的所有设备都有地址,它们可以连接,测试连接,断开连接 - 为什么不在一个抽象的“设备”类中使用它,并使所有设备继承它?
这可能是其中一种用法 - 用C#编写(对不起,如果我误解了实际使用情况:)这里我假设powersupply和dataLogger连接到接口,并且连接到笔记本电脑)。
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的引用。但是,如果它连接到接口,然后连接到记录器,PowerSupply必须只引用接口而不是记录器(因为它没有连接到它)。
我希望你能得到这个想法 - 它不会被称为'面向对象' - 将类视为真正的对象 - 如果一个对象可以做thing1,那么你应该在你的类中使用方法'thing1()';如果对象与object441有连接,那么该类应该具有对该类的引用。按照这个原则,看看它需要你...
当你掌握了它时,你的程序真的会从一些控制反转模式(IoC)模式中受益 - 这样你只需在开始时定义什么是记录器,什么是powerSupply,谁作为显示器执行,以及何时某人需要一些IoC容器提供的特定设备。这样你就不必每次在城里有新设备时重写代码 - 只需用IoC容器注册新类型,一切正常。