Skip to content

Instantly share code, notes, and snippets.

@jlsa
Created January 20, 2015 10:27
Show Gist options
  • Select an option

  • Save jlsa/ff362e3dcd4b8d4a2687 to your computer and use it in GitHub Desktop.

Select an option

Save jlsa/ff362e3dcd4b8d4a2687 to your computer and use it in GitHub Desktop.
Observer Pattern example
/**
*
* @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