Проектирование монитора изменения папки на C++ (Windows)


Что такое горячая папка?

Горячая папка — это такая же папка, как и любая другая. Горячей она становится, когда программа (которую мы будем кодировать на C++) отслеживает изменения.

Кто ее использует?

Программным входом может быть файл. Источником файла может быть оборудование, например, камера, генерирующая изображения, или стороннее программное обеспечение. Модуль следит за изменениями в папке и потребляет входные данные.

Как спроектировать?

Давайте подумаем! О том, что нам нужно:

Возможно, мы слышали о паттерне проектирования наблюдателя. Наблюдатели получают уведомления, когда Объект обновляется. Модель проектирования наблюдателя хорошо подходит для этой ситуации.

  • Наблюдатель — объект, отвечающий за получение событий от ОС об изменении папки. Скажем, наблюдающий за папкой. Наблюдатель является субъектом, потому что наблюдатель ведет себя как субъект, который получает обновления и уведомляет наблюдателей.

  • Слушатель обновлений — объект, хранящий список изменений, полученных от Субъекта. Слушатель обновлений является Наблюдателем. Модуль слушает субъекта и добавляет предстоящие изменения в потокобезопасную коллекцию. Это необходимо, почему? Потому что предположим сценарий, когда производитель производит N файлов в секунду, но когда у вас нет никакого слушателя, как модуль, то вы можете пропустить события при обработке предыдущих.

  • Handler — Object инстанцирует объект приемника и слушателя соответственно.

Давайте начнем!

Сначала мы определим два основных интерфейса ‘ISubject’ и ‘IObject’.

template <typename T>
class ISubject
{
    public:
        ISubject()          = default;
        virtual ~ISubject() = default;
        virtual AddObserver(const IObserver<T>* pObserver) = 0;
        virtual RemoveObserver(const IObserver<T>* pObserver) = 0;
        virtual NotifyObservers(const T& data) = 0;
};
Вход в полноэкранный режим Выход из полноэкранного режима
template <typename T>
class IObserver
{
    public:
        IObserver()          = default;
        virtual ~IObserver() = default;
        virtual Uptdate(const T& data) = 0;
};
Войти в полноэкранный режим Выход из полноэкранного режима
class DirectoryWatcher : public ISubject
{
    protected:
        std::string _strDirectory;
        HANDLE      _pChangeHandle;

        bool IsHandleValid();
        void Reset(const std::string& strDirectory);

    public: 
        DirectoryWatcher();
        ~DirectoryWatcher();

        bool Start(const std::string& strDirectory);
        void Stop();
        void AddObserver(const IObserver<std::string>* pObserver);
        void RemoveObserver(const IObserver<std::string>* pObserver);
        void NotifyObservers(const T& data);
};

Войти в полноэкранный режим Выход из полноэкранного режима
class UpdateListener : public IObserver
{
    protected:
        code_machina::BlockingCollection<std::string> _changeCollection;

    public: 
        UpdateListener();
        ~UpdateListener();

        bool Start(const std::string& strDirectory);
        void Stop();
        void AddObserver(const IObserver<std::string>* pObserver);
        void RemoveObserver(const IObserver<std::string>* pObserver);
        void NotifyObservers(const T& data);
};

Войти в полноэкранный режим Выйти из полноэкранного режима

Пожалуйста, прокомментируйте для получения дополнительной информации!

Оцените статью
Procodings.ru
Добавить комментарий