Created
January 20, 2015 10:27
-
-
Save jlsa/ff362e3dcd4b8d4a2687 to your computer and use it in GitHub Desktop.
Observer Pattern example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * | |
| * @author Joel Hoekstra | |
| * @version 1.0 (2015-01-20) | |
| * This example shows the observer pattern. | |
| * | |
| * The Listener class is the Observer | |
| * The Noise class is the Observable | |
| * | |
| * Unix Terminal - Compile is very easy! | |
| * g++ noise_listener.cpp -o noise_listener | |
| * | |
| */ | |
| #define KEY_Q 81 // used for quiting the game | |
| #define KEY_W 87 // to show more keys then one | |
| #define KEY_A 65 // idem | |
| #define KEY_S 83 // idem | |
| #define KEY_D 68 // idem | |
| #include <iostream> | |
| #include <string> | |
| #include <set> | |
| #include <vector> | |
| class Noise; // It will be there, I promise! | |
| /** | |
| * Abstract class Listener. (Observer) | |
| */ | |
| class Listener { | |
| public: | |
| virtual void update(Noise & Noise) = 0; | |
| }; | |
| /** | |
| * See, I promised! | |
| * The Noise class. Currently holds a boolean state. | |
| * Can also be a template for a lot more types :) | |
| * But in this example it is just active or not active | |
| */ | |
| class Noise | |
| { | |
| // holds the state | |
| bool state; | |
| // ordered list with Listeners | |
| std::set<Listener*> listeners; | |
| public: | |
| /** | |
| * Attach a Listener to this Noise | |
| */ | |
| void attachListener(Listener *o) { listeners.insert(o); } | |
| /** | |
| * Detach a Listener from this Noise | |
| */ | |
| void detachListener(Listener *o) { listeners.erase(o); } | |
| /** | |
| * If a state is changed, | |
| * call this method to update all Listeners | |
| */ | |
| void notifyListeners() | |
| { | |
| for(auto &o : listeners) | |
| { | |
| o->update(*this); | |
| } | |
| } | |
| /** | |
| * Get the current state | |
| */ | |
| bool getState() { return state; } | |
| /** | |
| * Change the state and notify the Listeners | |
| */ | |
| void changeState(const bool &s) | |
| { | |
| state = s; | |
| notifyListeners(); | |
| } | |
| }; | |
| /** | |
| * A ListenerImplementation extending Listener | |
| */ | |
| class ListenerImpl : public Listener | |
| { | |
| // hold the state of the Noise it listens to. | |
| bool state; | |
| public: | |
| /** | |
| * When update is called from within the Noise | |
| * Alter the state of the Listener | |
| */ | |
| void update(Noise & noise) override | |
| { | |
| state = noise.getState(); | |
| } | |
| /** | |
| * Returns the state within the Listener | |
| */ | |
| bool getState() { return state; } | |
| }; | |
| /** | |
| * The InputManager class that manages all the noises (keys) | |
| */ | |
| class InputManager | |
| { | |
| public: | |
| // Constructor | |
| InputManager(); | |
| // Destructor | |
| ~InputManager(); | |
| /** | |
| * Return the list with noises (keys) | |
| */ | |
| std::vector<Noise*> getKeys(); | |
| // The list with noises (keys) | |
| std::vector<Noise*> * keys; | |
| }; | |
| InputManager::InputManager() | |
| { | |
| // Init keys with new noises and the state set to false | |
| keys = new std::vector<Noise*>(); | |
| for(int i = 0; i <= 348; i++) { | |
| Noise *newNoise = new Noise(); | |
| newNoise->changeState(false); | |
| keys->push_back(newNoise); | |
| } | |
| } | |
| std::vector<Noise*> InputManager::getKeys() | |
| { | |
| return *keys; | |
| } | |
| InputManager::~InputManager() | |
| { | |
| keys->clear(); | |
| delete keys; | |
| keys = NULL; | |
| } | |
| int main() | |
| { | |
| // make a new input manager | |
| InputManager * inputManager = new InputManager(); | |
| // get the input managers key vector | |
| std::vector<Noise*> keys = inputManager->getKeys(); | |
| // Implementation for a listener | |
| ListenerImpl * listener = new ListenerImpl(); | |
| // assign a listener to a noise (key) | |
| keys.at(KEY_Q)->attachListener(listener); | |
| // init with value | |
| int running = 1; | |
| char ch = 'a'; | |
| while(running == 1) { | |
| // get the user input if q/Q then quit | |
| std::cout << "Press the q/Q to quit." << std::endl; | |
| std::cin >> ch; | |
| if(ch == 'q' || ch == 'Q') { | |
| keys.at(KEY_Q)->changeState(true); | |
| } | |
| // get the listeners current state - it may be changed | |
| if(listener->getState() == true) { | |
| running = 0; | |
| } | |
| } | |
| // end program | |
| std::cout << "Thanks for playing!" << std::endl; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment