Event Bus e padrão Observer em C++: da teoria à prática
No desenvolvimento moderno de software em C++, o baixo acoplamento entre componentes desempenha um papel importante. O padrão Observer (Observador) e sua evolução — Event Bus (Barramento de Eventos) — fornecem um mecanismo elegante para organizar a interação entre objetos sem criar dependências rígidas. Neste artigo, analisaremos detalhadamente como implementar esses padrões em C++, discutiremos suas vantagens e limitações e forneceremos exemplos práticos de código.
Padrão Observer: implementação clássica
O padrão Observer define uma relação "um para muitos" entre objetos: quando um objeto (sujeito) altera seu estado, todos os objetos dependentes (observadores) são notificados automaticamente. Em C++, a implementação clássica é a seguinte:
#include <iostream>#include <vector>#include <memory>#include <algorithm>
// Interface do observadorclass IObserver {public: virtual ~IObserver() = default; virtual void update(const std::string& message) = 0;};
// Observador concretoclass ConcreteObserver : public IObserver {private: std::string name;public: explicit ConcreteObserver(const std::string& n) : name(n) {} void update(const std::string& message) override { std::cout << "[" << name << "] Recebido: " << message << std::endl; }};
// Sujeito (objeto observado)class Subject {private: std::vector<std::shared_ptr<IObserver>> observers; std::string state;public: void attach(std::shared_ptr<IObserver> observer) { observers.push_back(observer); } void detach(std::shared_ptr<IObserver> observer) { observers.erase( std::remove(observers.begin(), observers.end(), observer), observers.end() ); } void notify() { for (auto& observer : observers) { observer->update(state); } } void setState(const std::string& newState) { state = newState; notify(); }};
int main() { Subject subject; auto obs1 = std::make_shared<ConcreteObserver>("Observador 1"); auto obs2 = std::make_shared<ConcreteObserver>("Observador 2"); subject.attach(obs1); subject.attach(obs2); subject.setState("Evento #1 ocorreu!"); subject.detach(obs1); subject.setState("Evento #2 sem o primeiro observador"); return 0;}Event Bus: barramento de eventos centralizado
O Event Bus expande a ideia do Observer, fornecendo um mecanismo centralizado de troca de mensagens. Em vez de cada sujeito armazenar uma lista de observadores, todas as inscrições e publicações passam por um único barramento. Isso permite:
- Reduzir o acoplamento — remetentes e destinatários não sabem nada uns sobre os outros.
- Simplificar a escalabilidade — novos tipos de eventos são adicionados sem alterar o código existente.
- Garantir flexibilidade — é possível adicionar e remover assinantes em tempo de execução.
Exemplo de implementação de Event Bus em C++ usando templates e std::function:
#include <iostream>#include <unordered_map>#include <functional>#include <any>#include <typeindex>#include <vector>#include <memory>
// Classe base para eventosstruct Event { virtual ~Event() = default;};
// Evento concretostruct UserLoginEvent : public Event { std::string username; explicit UserLoginEvent(std::string name) : username(std::move(name)) {}};
// Classe Event Busclass EventBus {private: std::unordered_map<std::type_index, std::vector<std::function<void(const std::any&)>>> hand