如何让我的课程更加独立于平台?

时间:2013-11-16 06:54:19

标签: c++ oop design-patterns

我有问题。我写了一个GPS模块,可以动态检测消息的类型,并在需要时配置它们。我是通过几个班级的组合来完成的。为了使代码更加独立于平台(stm32),我创建了一个具有基本i / o操作的IStreamDevice接口。有用。一切都看起来很棒,但课程显然是耦合的。这就是为什么我有几个问题:

  1. 如何避免将IStreamDevice传递给所有设备?
  2. 如何让整个设计更加独立于平台(和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看起来完全一样。我想听听任何人对设计所说的一切。

1 个答案:

答案 0 :(得分:1)

我认为您的设计没有任何固有问题。您的IStreamWriter接口似乎是底层总线的正确抽象,而不依赖于特定的总线详细信息。这符合依赖性倒置原则和按合同设计的方法。我也没有在你的班级中看到紧密耦合。根据接口规范,您通过其处理程序访问总线,而不依赖于实际总线处理类的实现。

在显示的代码中没有任何平台依赖。如果每个平台的总线处理不同,除了根据平台为IStreamWriter提供不同的实现之外,您无能为力。