From 53ee3df451210066593560a6159488190c7d3253 Mon Sep 17 00:00:00 2001 From: Shaun Reed Date: Tue, 11 May 2021 19:58:23 -0400 Subject: [PATCH] Add example of observer pattern in C++ --- cpp/patterns/CMakeLists.txt | 1 + cpp/patterns/observer/CMakeLists.txt | 20 ++++++++++++ cpp/patterns/observer/main.cpp | 33 +++++++++++++++++++ cpp/patterns/observer/observer.cpp | 39 +++++++++++++++++++++++ cpp/patterns/observer/observer.hpp | 47 ++++++++++++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 cpp/patterns/observer/CMakeLists.txt create mode 100644 cpp/patterns/observer/main.cpp create mode 100644 cpp/patterns/observer/observer.cpp create mode 100644 cpp/patterns/observer/observer.hpp diff --git a/cpp/patterns/CMakeLists.txt b/cpp/patterns/CMakeLists.txt index 33b78ef..49b3e4e 100644 --- a/cpp/patterns/CMakeLists.txt +++ b/cpp/patterns/CMakeLists.txt @@ -22,3 +22,4 @@ add_subdirectory(factory) add_subdirectory(prototype) add_subdirectory(abstract-factory) add_subdirectory(state) +add_subdirectory(observer) diff --git a/cpp/patterns/observer/CMakeLists.txt b/cpp/patterns/observer/CMakeLists.txt new file mode 100644 index 0000000..b538355 --- /dev/null +++ b/cpp/patterns/observer/CMakeLists.txt @@ -0,0 +1,20 @@ +############################################################################### +## Author: Shaun Reed ## +## Legal: All Content (c) 2021 Shaun Reed, all rights reserved ## +## About: A project for practicing the observer C++ design pattern ## +## ## +## Contact: shaunrd0@gmail.com | URL: www.shaunreed.com | GitHub: shaunrd0 ## +############################################################################## +# +cmake_minimum_required(VERSION 3.15) +project( + #[[NAME]] Observer + VERSION 1.0 + DESCRIPTION "An example of the state design pattern in C++" + LANGUAGES CXX +) +add_compile_options("-Wall") + +add_library(observer "observer.cpp") +add_executable(observer-test "main.cpp") +target_link_libraries(observer-test observer) diff --git a/cpp/patterns/observer/main.cpp b/cpp/patterns/observer/main.cpp new file mode 100644 index 0000000..609dddf --- /dev/null +++ b/cpp/patterns/observer/main.cpp @@ -0,0 +1,33 @@ + +#include + +#include "observer.hpp" + +int main(const int argc, const char * argv[]) +{ + Subject subject("Radio"); + Observer *john = new Observer(subject); + + // Test alerting john as the only subscribed observer + std::cout << "\nAlerting one observer...\n\n"; + subject.SendMessage("Alert 1\n"); + + + // Attach a new observer + Observer joe(subject); + // Alert all subscribed observers + std::cout << "\nAlerting all observers...\n\n"; + subject.SendMessage("Alert 2\n"); + + std::cout << std::endl; + // Detach joe from the subject + joe.Detach(); + // Send another alert to john + std::cout << "Alerting one observer...\n\n"; + subject.SendMessage("Alert 3\n"); + john->Detach(); + + // This alert will not be heard by anyone + std::cout << "\nAlerting no observers...\n\n"; + subject.SendMessage("Alert 4\n"); +} diff --git a/cpp/patterns/observer/observer.cpp b/cpp/patterns/observer/observer.cpp new file mode 100644 index 0000000..f8cf81f --- /dev/null +++ b/cpp/patterns/observer/observer.cpp @@ -0,0 +1,39 @@ + +#include "observer.hpp" + +void Subject::Notify() +{ + for (const auto &o : observerList) { o->Update(message);} +} + +void Subject::SendMessage(std::string message_) +{ + message = message_; + Notify(); +} + + +/******************************************************************************/ +// Observer + +int Observer::totalObservers = 0; + +Observer::Observer(Subject &s) : subject(s) { + std::cout << "Observer " << ++totalObservers << " is subscribed to " + << s.getName() << "\n"; + s.Attach(this); + number = totalObservers; +} + +void Observer::Update(std::string &message) +{ + std::cout << "Observer " << number << " has message from " + << subject.getName() << ": " << message; +} + +void Observer::Detach() +{ + std::cout << "Observer " << number << " has detached from " + << subject.getName() << std::endl; + subject.Detach(this); +} diff --git a/cpp/patterns/observer/observer.hpp b/cpp/patterns/observer/observer.hpp new file mode 100644 index 0000000..a36bb21 --- /dev/null +++ b/cpp/patterns/observer/observer.hpp @@ -0,0 +1,47 @@ + +#ifndef OBSERVER_HPP +#define OBSERVER_HPP + +#include +#include +#include + +#include "observer.hpp" + +class Observer; + +class Subject { +public: + Subject(std::string name_) : name(name_) {} + virtual ~Subject() { std::cout << name << " subject destroyed\n";} + + void Attach(Observer * o) { observerList.push_back(o);} + void Detach(Observer * o) { observerList.remove(o);} + void Notify(); + + void SendMessage(std::string message_); + inline std::string getName() const { return name;} + +private: + std::list observerList; + std::string message, name; +}; + + +/******************************************************************************/ +// Observer + +class Observer { +public: + Observer(Subject &s); + + void Update(std::string &message); + void Detach(); + +private: + Subject &subject; + int number; + static int totalObservers; +}; + +#endif // OBSERVER_HPP