我有问题。我写了一个GPS模块,可以动态检测消息的类型,并在需要时配置它们。我是通过几个班级的组合来完成的。为了使代码更加独立于平台(stm32),我创建了一个具有基本i / o操作的IStreamDevice
接口。有用。一切都看起来很棒,但课程显然是耦合的。这就是为什么我有几个问题:
如何让整个设计更加独立于平台(和os独立)?我们计划在不久的将来转向另一个操作系统。它符合POSIX标准。我想我可以在那里实现我的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
看起来完全一样。我想听听任何人对设计所说的一切。
答案 0 :(得分:1)
我认为您的设计没有任何固有问题。您的IStreamWriter
接口似乎是底层总线的正确抽象,而不依赖于特定的总线详细信息。这符合依赖性倒置原则和按合同设计的方法。我也没有在你的班级中看到紧密耦合。根据接口规范,您通过其处理程序访问总线,而不依赖于实际总线处理类的实现。
在显示的代码中没有任何平台依赖。如果每个平台的总线处理不同,除了根据平台为IStreamWriter
提供不同的实现之外,您无能为力。