cpp
examples
examples.cpp⚙️cpp
/**
* Design Patterns - Examples
* Compile: g++ -std=c++17 -Wall examples.cpp -o examples
*/
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <functional>
using namespace std;
// ============================================================
// SECTION 1: SINGLETON PATTERN
// ============================================================
class Logger {
static Logger* instance;
vector<string> logs;
Logger() = default;
public:
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
static Logger& getInstance() {
static Logger instance;
return instance;
}
void log(const string& msg) {
logs.push_back(msg);
cout << " [LOG] " << msg << endl;
}
void showAll() {
cout << " All logs (" << logs.size() << "):" << endl;
for (const auto& l : logs) cout << " - " << l << endl;
}
};
void demoSingleton() {
cout << "--- Singleton Pattern ---" << endl;
Logger::getInstance().log("First message");
Logger::getInstance().log("Second message");
// Same instance
auto& logger = Logger::getInstance();
logger.log("Third message");
logger.showAll();
}
// ============================================================
// SECTION 2: FACTORY PATTERN
// ============================================================
class Shape {
public:
virtual void draw() const = 0;
virtual ~Shape() = default;
};
class Circle : public Shape {
public:
void draw() const override { cout << " Drawing Circle" << endl; }
};
class Rectangle : public Shape {
public:
void draw() const override { cout << " Drawing Rectangle" << endl; }
};
class Triangle : public Shape {
public:
void draw() const override { cout << " Drawing Triangle" << endl; }
};
class ShapeFactory {
public:
static unique_ptr<Shape> create(const string& type) {
if (type == "circle") return make_unique<Circle>();
if (type == "rectangle") return make_unique<Rectangle>();
if (type == "triangle") return make_unique<Triangle>();
return nullptr;
}
};
void demoFactory() {
cout << "\n--- Factory Pattern ---" << endl;
auto shapes = {"circle", "rectangle", "triangle"};
for (const auto& s : shapes) {
auto shape = ShapeFactory::create(s);
if (shape) shape->draw();
}
}
// ============================================================
// SECTION 3: BUILDER PATTERN
// ============================================================
class Pizza {
public:
string dough, sauce, topping;
void show() const {
cout << " Pizza: " << dough << " dough, "
<< sauce << " sauce, " << topping << " topping" << endl;
}
};
class PizzaBuilder {
protected:
Pizza pizza;
public:
virtual PizzaBuilder& setDough() = 0;
virtual PizzaBuilder& setSauce() = 0;
virtual PizzaBuilder& setTopping() = 0;
Pizza build() { return pizza; }
virtual ~PizzaBuilder() = default;
};
class MargheritaBuilder : public PizzaBuilder {
public:
PizzaBuilder& setDough() override { pizza.dough = "thin"; return *this; }
PizzaBuilder& setSauce() override { pizza.sauce = "tomato"; return *this; }
PizzaBuilder& setTopping() override { pizza.topping = "mozzarella"; return *this; }
};
class PepperoniBuilder : public PizzaBuilder {
public:
PizzaBuilder& setDough() override { pizza.dough = "thick"; return *this; }
PizzaBuilder& setSauce() override { pizza.sauce = "spicy"; return *this; }
PizzaBuilder& setTopping() override { pizza.topping = "pepperoni"; return *this; }
};
void demoBuilder() {
cout << "\n--- Builder Pattern ---" << endl;
MargheritaBuilder mb;
Pizza margherita = mb.setDough().setSauce().setTopping().build();
margherita.show();
PepperoniBuilder pb;
Pizza pepperoni = pb.setDough().setSauce().setTopping().build();
pepperoni.show();
}
// ============================================================
// SECTION 4: OBSERVER PATTERN
// ============================================================
class IObserver {
public:
virtual void update(float temp) = 0;
virtual ~IObserver() = default;
};
class WeatherStation {
vector<IObserver*> observers;
float temperature = 0;
public:
void addObserver(IObserver* o) { observers.push_back(o); }
void setTemperature(float temp) {
temperature = temp;
notify();
}
void notify() {
for (auto* o : observers) o->update(temperature);
}
};
class PhoneDisplay : public IObserver {
string name;
public:
PhoneDisplay(const string& n) : name(n) {}
void update(float temp) override {
cout << " " << name << " shows: " << temp << "°C" << endl;
}
};
void demoObserver() {
cout << "\n--- Observer Pattern ---" << endl;
WeatherStation station;
PhoneDisplay phone1("Phone1"), phone2("Phone2");
station.addObserver(&phone1);
station.addObserver(&phone2);
cout << " Temperature changes to 25°C:" << endl;
station.setTemperature(25);
cout << " Temperature changes to 30°C:" << endl;
station.setTemperature(30);
}
// ============================================================
// SECTION 5: STRATEGY PATTERN
// ============================================================
class SortStrategy {
public:
virtual void sort(vector<int>& data) = 0;
virtual ~SortStrategy() = default;
};
class BubbleSort : public SortStrategy {
public:
void sort(vector<int>& data) override {
cout << " Using Bubble Sort" << endl;
// Simple bubble sort
for (size_t i = 0; i < data.size(); i++)
for (size_t j = 0; j < data.size() - 1; j++)
if (data[j] > data[j+1]) swap(data[j], data[j+1]);
}
};
class QuickSortStrategy : public SortStrategy {
public:
void sort(vector<int>& data) override {
cout << " Using Quick Sort (std::sort)" << endl;
std::sort(data.begin(), data.end());
}
};
class Sorter {
unique_ptr<SortStrategy> strategy;
public:
void setStrategy(unique_ptr<SortStrategy> s) { strategy = move(s); }
void sort(vector<int>& data) { strategy->sort(data); }
};
void demoStrategy() {
cout << "\n--- Strategy Pattern ---" << endl;
vector<int> data1 = {5, 2, 8, 1, 9};
vector<int> data2 = {5, 2, 8, 1, 9};
Sorter sorter;
sorter.setStrategy(make_unique<BubbleSort>());
sorter.sort(data1);
sorter.setStrategy(make_unique<QuickSortStrategy>());
sorter.sort(data2);
}
// ============================================================
// SECTION 6: DECORATOR PATTERN
// ============================================================
class Coffee {
public:
virtual string getDescription() const = 0;
virtual double getCost() const = 0;
virtual ~Coffee() = default;
};
class SimpleCoffee : public Coffee {
public:
string getDescription() const override { return "Coffee"; }
double getCost() const override { return 2.0; }
};
class CoffeeDecorator : public Coffee {
protected:
unique_ptr<Coffee> coffee;
public:
CoffeeDecorator(unique_ptr<Coffee> c) : coffee(move(c)) {}
};
class MilkDecorator : public CoffeeDecorator {
public:
using CoffeeDecorator::CoffeeDecorator;
string getDescription() const override {
return coffee->getDescription() + " + Milk";
}
double getCost() const override { return coffee->getCost() + 0.5; }
};
class SugarDecorator : public CoffeeDecorator {
public:
using CoffeeDecorator::CoffeeDecorator;
string getDescription() const override {
return coffee->getDescription() + " + Sugar";
}
double getCost() const override { return coffee->getCost() + 0.2; }
};
void demoDecorator() {
cout << "\n--- Decorator Pattern ---" << endl;
auto coffee = make_unique<SimpleCoffee>();
cout << " " << coffee->getDescription() << ": $" << coffee->getCost() << endl;
auto withMilk = make_unique<MilkDecorator>(move(coffee));
cout << " " << withMilk->getDescription() << ": $" << withMilk->getCost() << endl;
auto withSugar = make_unique<SugarDecorator>(move(withMilk));
cout << " " << withSugar->getDescription() << ": $" << withSugar->getCost() << endl;
}
// ============================================================
// SECTION 7: COMMAND PATTERN
// ============================================================
class Command {
public:
virtual void execute() = 0;
virtual void undo() = 0;
virtual ~Command() = default;
};
class Light {
public:
void on() { cout << " Light ON" << endl; }
void off() { cout << " Light OFF" << endl; }
};
class LightOnCommand : public Command {
Light& light;
public:
LightOnCommand(Light& l) : light(l) {}
void execute() override { light.on(); }
void undo() override { light.off(); }
};
class LightOffCommand : public Command {
Light& light;
public:
LightOffCommand(Light& l) : light(l) {}
void execute() override { light.off(); }
void undo() override { light.on(); }
};
class RemoteControl {
vector<unique_ptr<Command>> history;
public:
void executeCommand(unique_ptr<Command> cmd) {
cmd->execute();
history.push_back(move(cmd));
}
void undoLast() {
if (!history.empty()) {
history.back()->undo();
history.pop_back();
}
}
};
void demoCommand() {
cout << "\n--- Command Pattern ---" << endl;
Light light;
RemoteControl remote;
remote.executeCommand(make_unique<LightOnCommand>(light));
remote.executeCommand(make_unique<LightOffCommand>(light));
cout << " Undo:" << endl;
remote.undoLast();
}
// ============================================================
// MAIN
// ============================================================
int main() {
cout << "╔══════════════════════════════════════╗" << endl;
cout << "║ DESIGN PATTERNS - EXAMPLES ║" << endl;
cout << "╚══════════════════════════════════════╝" << endl;
demoSingleton();
demoFactory();
demoBuilder();
demoObserver();
demoStrategy();
demoDecorator();
demoCommand();
cout << "\n=== Complete ===" << endl;
return 0;
}