Skip to content

Instantly share code, notes, and snippets.

@kenpower
Last active March 12, 2025 21:58
Show Gist options
  • Save kenpower/1536b7eb2f2358af2bf6bd7254cdccbc to your computer and use it in GitHub Desktop.
Save kenpower/1536b7eb2f2358af2bf6bd7254cdccbc to your computer and use it in GitHub Desktop.
The evolution demonstrates:
Starting with a single strategy for a game action.
Expanding to multiple strategies executed together.
Refactoring into a subject-observer structure.
Adding dynamic management for an arbitrary number of observers.
Strategy (Step 1): A single game-related behavior (e.g., starting the game) is encapsulated and executed, making it interchangeable with other behaviors like pausing or exiting.
Observer (Step 4): Multiple game components (observers) are notified of the button press and react in their own way (e.g., starting the game, playing a sound, updating the score).
#include <iostream>
// Abstract strategy interface
class ButtonPressHandler {
public:
virtual void handlePress() = 0;
virtual ~ButtonPressHandler() = default;
};
// Context class that uses the strategy
class GameController {
private:
ButtonPressHandler* handler;
public:
void pressXButton() {
handler->handlePress(); // Delegate to the strategy
}
};
// Concrete strategy
class ResetLevelHandler : public ButtonPressHandler {
public:
void handlePress() override {
std::cout << "Controller button pressed - Level Resett\n";
}
void setHandler(ButtonPressHandler* h){
handler=h;
}
};
class UpdateScoreHandler : public ButtonPressHandler {
public:
void handlePress() override {
std::cout << "Controller button pressed - Score updated\n";
}
};
int main() {
ResetLevelHandler reseter;
UpdateScoreHandler updater;
Controller controller();
controller.setHandler(&reseter)
controller.pressButton();
Controller controller(&updater);
controller.pressXButton();
// What if we wanted to call both strategies at same time????
return 0;
}
/*
extend the Controller to hold multiple game-related strategies
(e.g., starting the game, playing a sound, and updating the score)
and execute all of them when the button is pressed.
*/
#include <iostream>
#include <vector>
// Abstract strategy interface (unchanged)
class ButtonPressHandler {
public:
virtual void handlePress() = 0;
virtual ~ButtonPressHandler() = default;
};
// Context class modified to hold multiple strategies
class GameController {
private:
std::vector<ButtonPressHandler*> handlers;
public:
void addHandler(ButtonPressHandler* h) {
handlers.push_back(h);
}
void pressXButton() {
for (auto h : handlers) {
h->handlePress(); // Execute all strategies
}
}
};
// Concrete strategies
class StartGameHandler : public ButtonPressHandler {
public:
void handlePress() override {
std::cout << "Controller button pressed - Game started\n";
}
};
class PlaySoundHandler : public ButtonPressHandler {
public:
void handlePress() override {
std::cout << "Controller button pressed - Sound played\n";
}
};
class UpdateScoreHandler : public ButtonPressHandler {
public:
void handlePress() override {
std::cout << "Controller button pressed - Score updated\n";
}
};
// Usage
int main() {
StartGameHandler starter;
PlaySoundHandler sound;
UpdateScoreHandler score;
Controller controller;
controller.addHandler(&starter);
controller.addHandler(&sound);
controller.addHandler(&score);
controller.pressXButton();
return 0;
}
/*
We'll refactor the code to use a Subject base class that manages observers (formerly strategies),
with Controller inheriting from it to notify all observers of a button press.
*/
#include <iostream>
#include <vector>
// Observer interface (renamed from ButtonPressHandler)
class ButtonPressObserver {
public:
virtual void update() = 0;
virtual ~ButtonPress() = default;
};
// Subject base class to manage observers
class Subject {
private:
std::vector<Observer*> observers;
public:
void addObserver(Observer* o) {
observers.push_back(o);
}
void notifyObservers() {
for (auto o : observers) {
o->update();
}
}
};
// Concrete subject
class Controller : public Subject {
public:
void pressXButton() {
std::cout << "Controller button pressed\n";
notifyObservers(); // Notify all observers
}
};
// Concrete observers (formerly strategies)
class StartGameHandler : public ButtonPressObserver {
public:
void update() override {
std::cout << " - Game started\n";
}
};
class PlaySoundHandler : public ButtonPressObserver {
public:
void update() override {
std::cout << " - Sound played\n";
}
};
class UpdateScoreHandler : public ButtonPressObserver {
public:
void update() override {
std::cout << " - Score updated\n";
}
};
// Usage
int main() {
StartGameHandler starter;
PlaySoundHandler sound;
UpdateScoreHandler score;
Controller controller;
controller.addObserver(&starter);
controller.addObserver(&sound);
controller.addObserver(&score);
controller.pressXButton();
return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
// Observer interface
class Observer {
public:
virtual void update() = 0;
virtual ~Observer() = default;
};
// Subject base class with add/remove functionality
class Subject {
private:
std::vector<Observer*> observers;
public:
void addObserver(Observer* o) {
observers.push_back(o);
}
void removeObserver(Observer* o) {
observers.erase(
std::remove(observers.begin(), observers.end(), o),
observers.end()
);
}
void notifyObservers() {
for (auto o : observers) {
o->update();
}
}
};
// Concrete subject
class Controller : public Subject {
public:
void pressXButton() {
std::cout << "Controller button pressed\n";
notifyObservers();
}
};
// Concrete observers
class StartGameHandler : public Observer {
public:
void update() override {
std::cout << " - Game started\n";
}
};
class PlaySoundHandler : public Observer {
public:
void update() override {
std::cout << " - Sound played\n";
}
};
class UpdateScoreHandler : public Observer {
public:
void update() override {
std::cout << " - Score updated\n";
}
};
// Usage
int main() {
StartGameHandler starter;
PlaySoundHandler sound;
UpdateScoreHandler score;
Controller controller;
// Add observers
controller.addObserver(&starter);
controller.addObserver(&sound);
controller.addObserver(&score);
controller.pressXButton();
std::cout << "\nRemoving sound observer\n";
controller.removeObserver(&sound);
controller.pressXButton();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment