我有三种类型的设备(USB、COM 和无线)和一个用于连接它们的 PC 软件。每个设备都具有连接RS485网络、读取和写入数据等功能。在 PC 软件上,我必须实现应用程序层类才能与设备一起使用。我正在寻找一些设计模式来编写应用程序层和传输层之间的连接。第一个想法是编写抽象类DataLink,每个设备都将从抽象类接口(interface)继承(纯OOP):
class DataLink {
public:
virtual bool read() = 0;
virtual bool write() = 0;
};
class USBDevice : public DataLink {
public:
bool read() { /* some code */ }
bool write() { /* some code */ }
bool specificUSBFunction() { /* some code */ }
};
class COMDevice : public DataLink {
public:
bool read() { /* some code */ }
bool write() { /* some code */ }
bool specificCOMFunction(){ /* some code */ }
};
DataLink *dl = new COMDevice();
dl->read();
dl->write();
现在,如果我想使用特定的 USB 或 COM 功能,我必须使用丑陋的强制转换。 另一个问题是这个类必须是单例的,因为我们只有一个可用的设备,所以我们不能创建多个对象。 我正在寻找一种使用 C++(可以是 v11 或 v14)来执行此操作的好方法。
最佳答案
首先,由于您有一个抽象类,我强烈建议您考虑定义一个抽象构造函数。
class DataLink {
public:
virtual bool read() = 0;
virtual bool write() = 0;
virtual ~DataLink() {}
};
现在创 build 备会引发一些问题。您的多态设计宁愿代表参数化的 factory method ,其中参数(配置数据?)将告诉您是否要创建 COM、USB 或 WIFI 设备:
DataLink *dl = CreateDevice("COM"); // For example. COuld use an enum as well
但是你添加了另一个约束:
This class must be singleton because we have only one device available so we cannot create multiple objects.
事实上,单例的目的不仅是为了确保单个实例,也是为了确保对它的全局访问点。如果您不需要这样的全局访问,我强烈建议不要在这里使用单例。
顺便说一句,您的限制引发了其他问题:每种类型您都有一台设备吗?或者您是否拥有一台设备,无论其类型是什么?最重要的是,难道有一天您必须支持多种设备吗?
因此,从概念上讲,即使您当前只有一个设备,唯一性也不是通用设备类的属性,也不是其具体实现的属性。这只是您当前创建数据链接的用例。因此,我建议您实现一个工厂并派生一个特定于应用程序的工厂来实现您的创建约束;
class DeviceFactory { // application independent
public:
enum DeviceType { COMDevice, USBDevice, ... };
DataLink *CreateDevice(std::string devicename, DeviceType t);
};
class MySpecificFactory : public DeviceFactory { // application specific constraints
std::map<std::string,DataLink*> objects;
public:
DataLink *CreateDevice(std::string devicename, DeviceType t) {
if (objects.count(devicename)!=0) {
// device already exists, either report an error, or
// return the previously created object with the same name (provided it has the same type)
...
}
else {
DataLink* dl = DeviceFactory::CreateDevice(devicename,t);
if (dl)
objects[devicename]=dl;
return dl;
}
}
};
链接特定功能的处理与创建问题正交。最简单、最安全的方法当然是动态转换:
if (COMDevice* cd=dynamic_cast<COMDevice>(dl)) // nullptr if it isn't a COMDevice
cd->COMFunction();
else ...
如果不知道链接特定功能的目的以及它们在应用程序上下文中的关系,就很难就更具体的模式提供建议。
关于c++ - 设备数据链路设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34500758/