C++ 如何使我的类更加独立于平台?
我有个问题。我已经编写了一个GPS模块,可以在飞行中检测消息的类型,并在需要时进行配置。我已经写了好几节课了。为了使代码更独立于平台(stm32),我创建了一个具有baic I/o操作的C++ 如何使我的类更加独立于平台?,c++,oop,design-patterns,C++,Oop,Design Patterns,我有个问题。我已经编写了一个GPS模块,可以在飞行中检测消息的类型,并在需要时进行配置。我已经写了好几节课了。为了使代码更独立于平台(stm32),我创建了一个具有baic I/o操作的IStreamDevice接口。它起作用了。一切看起来都很好,但这两个班显然是结合在一起的。这就是我有几个问题的原因: 如何避免将IStreamDevice传递给所有设备 如何使整个设计更加独立于平台(和操作系统)?我们计划在最近的将来迁移到另一个操作系统。它符合POSIX标准。我想我将能够在那里实现我的IStr
IStreamDevice
接口。它起作用了。一切看起来都很好,但这两个班显然是结合在一起的。这就是我有几个问题的原因:
IStreamDevice
接口(我可以使用的总线是UART和SPI。在我当前的版本中,我只使用UART)。我错了吗
class IStreamDevice
{
public:
virtual ~IStreamDevice() {}
virtual uint32_t read(uint8_t* data, uint32_t size) = 0;
virtual uint32_t write(const uint8_t* data, uint32_t size) = 0;
virtual uint32_t bytesToRead() const = 0;
virtual uint32_t bytesToWrite() const = 0;
};
class GPSModule {
public:
GPSModule(periph::IStreamDevice *source);
~GPSModule();
void turnDevice1Messages();
void turnDevice2Messages();
void configureDevice1(...);
void configureDevice2(...);
void Scan();
private:
Device1Configurator *_device1_configurator;
Device2Configurator *_device2_configurator;
StreamDeviceScanner*_scanner;
periph::IStreamDevice *_source;
};
GPSModule::GPSModule(periph::IStreamDevice *source): _source(source)
{
_scanner= new StreamDeviceScanner(_source);
_device1_configurator = new Device1Configurator(_source);
_device2_configurator = new Device2Configurator(_source);
}
GPSModule::~GPSModule()
{
delete _scanner;
}
void GPSModule::Scan()
{
_scanner->Scan();
}
void GPSModule::turnDevice1Messages() {
_device1_configurator->turnMessages();
}
class StreamDeviceScanner{
public:
StreamDeviceScanner(periph::IStreamDevice *source);
~StreamDeviceScanner();
void Scan();
private:
typedef enum
{
WAITING_SYNC,
WAITING_DEVICE1_MSG,
WAITING_DEVICE2_MSG
} states_t;
periph::IStreamDevice *_source;
ProtocolScanner *_protocol_scanner;
states_t _state;
private:
states_t _catchSync();
uint32_t _read(uint8_t* data, uint32_t length) { return _source->read(data,length); }
uint32_t _bytesToRead() const { return _source->bytesToRead(); }
};
StreamDeviceScanner::StreamDeviceScanner(periph::IStreamDevice *source):
_source(source),
_state(WAITING_SYNC)
{
_protocol_scanner = new ProtocolScanner(source);
}
StreamDeviceScanner::~StreamDeviceScanner()
{
delete _protocol_scanner;
}
void StreamDeviceScanner::Scan()
{
while (_source->bytesToRead()) {
switch (_state)
{
case WAITING_SYNC:
_state = _catchSync();
break;
case WAITING_DEVICE1_MSG:
_protocol_scanner->Device1Scan()
_state = WAITING_SYNC;
break;
case WAITING_DEVICE2_MSG:
_protocol_scanner->Device2Scan()
_state = WAITING_SYNC;
break;
}
}
}
class ProtocolScanner {
private:
Device1Scanner *_Device1Scanner;
Device2Scanner *_Device2Scanner;
public:
ProtocolScanner(periph::IStreamDevice *source)
{
_Device1Scanner = new Device1Scanner(source);
_Device2Scanner = new Device2Scanner(source);
}
~ProtocolScanner()
{
delete _Device1Scanner;
delete _Device1Scanner;
}
bool Device1Scan() const { return _Device1Scanner->Scan(); }
bool Device2Scan() const { return _Device2Scanner->Scan(); }
};
class Device1Scanner {
public:
Device1Scanner(periph::IStreamDevice *source);
~Device1Scanner();
bool Scan();
private:
enum { BUFFER_LENGTH = 8192 };
typedef enum {
Waiting_Header,
Waiting_Payload,
Waiting_Checksum
} state_t;
uint8_t _buffer[BUFFER_LENGTH];
periph::IStreamDevice *_source;
state_t _state;
Device1Parser *_destination;
Device1Scanner::NovatelMessage _message;
private:
uint32_t _read(uint8_t* data, uint32_t size) { return _source->read(data,size); }
const uint32_t _bytesToRead() const { return _source->bytesToRead(); }
bool _receiveHeader();
bool _receivePayload();
bool _receiveChecksum();
bool _validChecksum() const;
};
Device2Scanner
看起来完全一样。我想听听任何人对设计的意见我看你的设计没有任何固有的问题。您的
IStreamWriter
接口似乎是底层总线的适当抽象,而不依赖于特定的总线细节。这符合依赖倒置原则和契约式设计方法。我也没有看到你们班上的紧密耦合。根据接口规范,您通过其处理程序访问总线,而不依赖于实际总线处理类的实现
所示代码中没有任何平台依赖性。如果每个平台的总线处理不同,那么除了根据平台为
IStreamWriter
提供不同的实现之外,您没有什么可以做的 编辑完这个问题后,请给我发送一封邮件。所以没有什么好办法可以避免将IStreamWriter传递给所有的班级成员?当我看代码时,我非常怀疑它是否能做得更好。我想得太多了吗?正如我在上面所写的,将IStreamDevice传递给所有成员让我头疼。@enter\u\u机器人好吧,你必须以某种方式链接不同的对象,对吗?这里没有太多的选择。StreamWriter
可以从您身边经过;它可以是全球性的(通常,这是一个坏主意,但这取决于环境和上下文)。您还可以使用外部存储对象来存储您的StreamWriter
,并从需要的任何位置在内部查询存储-但它不会为您节省任何东西,而且这是一个严重的过度工程,您只需要将用户连接到此存储,而不是连接到实际的StreamWriter
再多说一句——通常您对软件提出的要求越多,您的开销就越大(可能是性能、复杂性或任何其他类型的影响)。这里需要将您的实体显式连接到StreamWriter
,并且需要编写接口(这是最重要的部分,您可以接受)-IMHO,这是为您获得的模块化和平台独立性付出的一个小代价。