Я создал два абстрактных класса Subject и Observer, которые определяют классический интерфейс шаблонов Observer. Я извлекаю из них реализацию шаблона Observer. Наблюдатель может выглядеть так:
void MyClass::Update(Subject *subject)
{
if(subject == myService_)
{
DoSomething();
}
else if(subject == myOtherService_)
{
DoSomethingElse();
}
}
Это хорошо, и это говорит мне, кто что-то изменил. Однако, это не говорит мне, что изменилось. Иногда это нормально, потому что я просто собираюсь запросить у субъекта последние данные, но в других случаях мне нужно знать, что именно изменилось в предмете. Я заметил, что в Java есть метод notifyObservers () и метод notifyObservers (Object arg) для предположительного указания деталей об изменениях.
В моем случае мне нужно знать, произошло ли одно или несколько различных действий с субъектом, и, если это конкретное действие, узнать целое число, связанное с этим действием.
Итак, мои вопросы:
- Как в C ++ можно передать универсальный аргумент (как это делает Java)?
- Является ли Observer даже лучшим паттерном? Возможно, какая-то система событий?
ОБНОВИТЬ
Я нашел эту статью, в которой рассказывается о шаблоне шаблона Observer: реализация шаблона Subject / Observer с помощью шаблонов . Это заставило меня задуматься, не могли бы вы создать шаблон аргумента.
Я нашел этот вопрос переполнения стека, в котором говорится о шаблонировании аргумента: Шаблон Subject Observer на основе шаблона - должен ли я использовать static_cast или dynamic_cast . Однако у ОП, похоже, есть проблема, на которую никто не ответил.
Другая вещь, которую я мог бы сделать, это изменить метод Update, чтобы взять объект EventArg, как в:
void MyClass::Update(Subject *subject, EventArg arg)
{
...
А затем создайте подклассы EventArg для конкретных данных аргумента, а затем, я думаю, приведите их обратно к конкретному подклассу в методе обновления.
ОБНОВЛЕНИЕ 2
Также нашел статью, О создании асинхронных основ C ++ на основе сообщений; часть 2, в которой обсуждается, как субъект сообщает подробности о том, что изменилось.
Сейчас я серьезно думаю об использовании Boost.Signals . Использование моего собственного шаблона наблюдателя имело смысл, когда оно было простым, но шаблонирование типа и аргумента начинает усложняться. И мне может понадобиться безопасность потоков Boost.Signals2.
ОБНОВЛЕНИЕ 3
Я также нашел несколько интересных статей по шаблону наблюдателя:
Обобщающий наблюдатель Херб Саттер
Реализация шаблона наблюдателя в C ++ - Часть 1
Опыт реализации шаблона проектирования наблюдателя (часть 2)
Опыт реализации шаблона проектирования наблюдателя (часть 3)
Тем не менее, я переключил свою реализацию на использование Boost.Signals, который, возможно, немного раздулся для моих целей, успешно работает. И, вероятно, любые проблемы вздутия или скорости не имеют значения.