1. Обзор
Шаблон наблюдателя определяет отношение зависимости между объектами "один ко многим". Когда состояние объекта изменяется, все объекты, которые зависят от него, получают уведомление и автоматически обновляются.
2. Пример кода
#include <список>
предмет класса;
class Observer
{ public: virtual ~ Observer(); виртуальная пустота Update(Subject* theChangedSubject) = 0; защищено: Наблюдатель(); };
class Subject
{ public: virtual ~Subject(){} virtual void Attach(Observer* o) { _observers->push_back(o); } виртуальная пустота Detach(Observer* o) { _observers->remove(o); } virtual void Notity() { std::list<Observer*>::iterator it = _observers->begin(); while (it != _observers->end()) { (*it)->Update(this); ++это; } } защищено: Тема(); частный: std::list<Observer*> *_observers; };
Приведенный выше код представляет собой простой код шаблона проектирования наблюдателя с четкой логикой, но он не универсален и действителен только для конкретных наблюдателей, то есть он должен быть производным классом абстрактного класса Observer, и этот наблюдатель не может иметь параметры, а параметры интерфейса не поддерживают изменения, то наблюдатель не сможет справиться с изменениями интерфейса. Так как же нам решить эту проблему? Это можно изменить, используя некоторые возможности C++11.
class NonCopyable
{ protected: NonCopyable() = default; ~NonCopyable() = default; NonCopyable(const NonCopyable&) = delete; //Отключить построение копирования NonCopyable& operator = (const NonCopyable&) = delete; //Отключить построение присваивания };
#include <iostream>
#include <string>
#include <functional>
#include <map>
использование пространства имен std;
template<typename Func>
class Events : NonCopyable
{ public: Events(){} ~Events(){} //регистрация наблюдателя, поддержка rvalue int Connect(Func&& f) { return Assgin(f); } //регистрация наблюдателя } int Connect(Func& f) { return Assgin(f); } //Удаляем наблюдатель void Disconnect(int key) { m_connections.erase(key); } private: //Сохраняем наблюдатель и присваиваем ему номер template< typename F> int Assgin(F&& f) { int k = m_observerId++;
m_connections.emplace(k, std::forward<F> (f));
}
интервал m_observerId = 0;
std::map<int, Func> m_connections;
};
Наблюдатель, реализованный C++11, для внутреннего списка общих функций, наблюдателю нужно только зарегистрировать функцию наблюдателя, что устраняет сильную связь, вызванную наследованием. Интерфейс уведомлений использует вариативные шаблоны и поддерживает произвольные параметры, что исключает влияние изменений интерфейса.