Event Bus e padrão Observer em C++: implementação em C++ moderno

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Event Bus e padrão Observer em C++: da teoria à implementação moderna



No desenvolvimento moderno em C++, surge cada vez mais a necessidade de um mecanismo flexível de troca de mensagens entre componentes que não precisam se conhecer diretamente. O padrão Observer e sua evolução — Event Bus — resolvem esse problema, permitindo construir sistemas fracamente acoplados e extensíveis. Neste artigo, vamos analisar como implementar um Event Bus em C++ usando a biblioteca padrão (C++17/20) e ver exemplos práticos.



Padrão Observer: a base 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 automaticamente notificados. Em C++, a implementação clássica é assim:



#include <iostream>#include <vector>#include <memory>#include <algorithm>

// Classe base do observadorclass IObserver {public: virtual ~IObserver() = default; virtual void update(const std::string& message) = 0;};

// Sujeito (publicador)class Subject {private: std::vector<std::weak_ptr<IObserver>> observers_;public: void attach(std::shared_ptr<IObserver> observer) { observers_.push_back(observer); }

void detach(std::shared_ptr<IObserver> observer) { observers_.erase( std::remove_if(observers_.begin(), observers_.end(), [&observer](const std::weak_ptr<IObserver>& wp) { auto sp = wp.lock(); return !sp || sp == observer; }), observers_.end() ); }

void notify(const std::string& message) { for (auto it = observers_.begin(); it != observers_.end(); ) { if (auto sp = it->lock()) { sp->update(message); ++it; } else { it = observers_.erase(it); // remove referências "mortas" } } }};

// Observador concretoclass ConcreteObserver : public IObserver {private: std::string name_;public: ConcreteObserver(const std::string& name) : name_(name) {} void update(const std::string& message) override { std::cout << "[" << name_ << "] recebeu: " << message << std::endl; }};

int main() { auto subject = std::make_shared<Subject>(); auto obs1 = std::make_shared<ConcreteObserver>("Observador 1"); auto obs2 = std::make_shared<ConcreteObserver>("Observador 2");

subject->attach(obs1); subject->attach(obs2); subject->notify("Evento ocorreu!");

subject->detach(obs1); subject->notify("Apenas para o segundo");

return 0;}


Este código funciona, mas tem limitações: todos os observadores devem herdar de IObserver e as mensagens precisam ser strings. Na prática, é necessário um sistema mais flexível.



Event Bus: evolução moderna



Event Bus é um barramento centralizado através do qual os componentes podem publicar eventos e se inscrever neles. Principais diferenças do Observer clássico:

  • Eventos tipados — cada evento tem seu próprio tipo de dados.
  • Sem hierarquia rígida — os assinantes não precisam herdar uma interface comum.
  • Barramento global ou local — é possível ter um único Event Bus para toda a aplicação ou vários isolados.


Implementação do Event Bus em C++17/20 com std::any



Usamos std::any para armazenar dados de qualquer tipo e std::function para os manipuladores. Para separar eventos por tipo, aplicamos std::type_index.



#include <iostream>#include <any>#include <function                    

Recommendations