cpp

exercises

exercises.cpp⚙️
/**
 * Design Patterns - Exercises
 * Compile: g++ -std=c++17 -Wall exercises.cpp -o exercises
 */

#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <map>
using namespace std;

// ============================================================
// Exercise 1: Database Connection Pool (Singleton) ⭐⭐
// ============================================================

// TODO: Implement a connection pool as singleton
// - Maximum 5 connections
// - getConnection() returns available connection
// - releaseConnection() returns to pool

void exercise1() {
    // auto& pool = ConnectionPool::getInstance();
    // auto conn = pool.getConnection();
    // conn->execute("SELECT * FROM users");
    // pool.releaseConnection(conn);
    cout << "(Implement connection pool singleton)" << endl;
}

// ============================================================
// Exercise 2: Document Factory ⭐⭐
// ============================================================

// TODO: Create factory for document types
// - PDF, Word, Excel documents
// - Each has open(), edit(), save() methods

void exercise2() {
    // auto doc = DocumentFactory::create("pdf");
    // doc->open();
    // doc->edit("content");
    // doc->save();
    cout << "(Implement document factory)" << endl;
}

// ============================================================
// Exercise 3: Sandwich Builder ⭐⭐
// ============================================================

// TODO: Builder for custom sandwiches
// - bread, protein, cheese, vegetables, sauces

void exercise3() {
    // Sandwich s = SandwichBuilder()
    //     .setBread("wheat")
    //     .setProtein("turkey")
    //     .setCheese("swiss")
    //     .addVegetable("lettuce")
    //     .addSauce("mayo")
    //     .build();
    cout << "(Implement sandwich builder)" << endl;
}

// ============================================================
// Exercise 4: Stock Market Observer ⭐⭐
// ============================================================

// TODO: Stock ticker with multiple observers
// - StockMarket subject
// - Investors get notified of price changes

void exercise4() {
    // StockMarket market;
    // Investor investor("Alice");
    // market.subscribe(&investor, "AAPL");
    // market.updatePrice("AAPL", 150.50);
    cout << "(Implement stock market observer)" << endl;
}

// ============================================================
// Exercise 5: Payment Strategy ⭐⭐
// ============================================================

// TODO: Multiple payment methods
// - CreditCard, PayPal, Bitcoin
// - Checkout uses selected strategy

void exercise5() {
    // Checkout checkout;
    // checkout.setPaymentMethod(make_unique<CreditCard>("1234..."));
    // checkout.pay(100.00);
    cout << "(Implement payment strategy)" << endl;
}

// ============================================================
// Exercise 6: Pizza Decorator ⭐⭐
// ============================================================

// TODO: Pizza with toppings as decorators
// - BasePizza
// - CheeseDecorator, PepperoniDecorator, etc.
// - Each adds to cost and description

void exercise6() {
    // auto pizza = make_unique<BasePizza>();
    // pizza = make_unique<CheeseDecorator>(move(pizza));
    // pizza = make_unique<PepperoniDecorator>(move(pizza));
    // cout << pizza->getDescription() << ": $" << pizza->getCost();
    cout << "(Implement pizza decorator)" << endl;
}

// ============================================================
// Exercise 7: Text Editor Commands (Undo/Redo) ⭐⭐⭐
// ============================================================

// TODO: Commands with undo/redo
// - InsertText, DeleteText, ReplaceText
// - Editor maintains command history

void exercise7() {
    // TextEditor editor;
    // editor.execute(make_unique<InsertCommand>("Hello"));
    // editor.execute(make_unique<InsertCommand>(" World"));
    // editor.undo();
    // editor.redo();
    cout << "(Implement text editor commands)" << endl;
}

// ============================================================
// Exercise 8: State Machine (Vending Machine) ⭐⭐⭐
// ============================================================

// TODO: Vending machine states
// - IdleState, CoinInsertedState, DispenseState
// - Transitions on events

void exercise8() {
    // VendingMachine vm;
    // vm.insertCoin();   // Idle -> CoinInserted
    // vm.selectItem();   // CoinInserted -> Dispense
    // vm.dispense();     // Dispense -> Idle
    cout << "(Implement vending machine states)" << endl;
}

// ============================================================
// MAIN
// ============================================================

int main() {
    cout << "=== Design Patterns Exercises ===" << endl;
    
    cout << "\nEx1: Connection Pool" << endl;
    exercise1();
    
    cout << "\nEx2: Document Factory" << endl;
    exercise2();
    
    cout << "\nEx3: Sandwich Builder" << endl;
    exercise3();
    
    cout << "\nEx4: Stock Market Observer" << endl;
    exercise4();
    
    cout << "\nEx5: Payment Strategy" << endl;
    exercise5();
    
    cout << "\nEx6: Pizza Decorator" << endl;
    exercise6();
    
    cout << "\nEx7: Text Editor Commands" << endl;
    exercise7();
    
    cout << "\nEx8: Vending Machine States" << endl;
    exercise8();
    
    return 0;
}

// ============================================================
// ANSWERS
// ============================================================
/*
Ex1:
class Connection {
public:
    void execute(const string& sql) { cout << "Executing: " << sql << endl; }
};

class ConnectionPool {
    vector<shared_ptr<Connection>> available;
    vector<shared_ptr<Connection>> inUse;
    static const int MAX = 5;
    ConnectionPool() {
        for (int i = 0; i < MAX; i++)
            available.push_back(make_shared<Connection>());
    }
public:
    static ConnectionPool& getInstance() {
        static ConnectionPool instance;
        return instance;
    }
    shared_ptr<Connection> getConnection() {
        if (available.empty()) return nullptr;
        auto conn = available.back();
        available.pop_back();
        inUse.push_back(conn);
        return conn;
    }
    void releaseConnection(shared_ptr<Connection> conn) {
        auto it = find(inUse.begin(), inUse.end(), conn);
        if (it != inUse.end()) {
            inUse.erase(it);
            available.push_back(conn);
        }
    }
};

Ex4:
class StockObserver {
public:
    virtual void update(const string& stock, double price) = 0;
};

class StockMarket {
    map<string, vector<StockObserver*>> subscribers;
    map<string, double> prices;
public:
    void subscribe(StockObserver* o, const string& stock) {
        subscribers[stock].push_back(o);
    }
    void updatePrice(const string& stock, double price) {
        prices[stock] = price;
        for (auto* o : subscribers[stock]) o->update(stock, price);
    }
};

class Investor : public StockObserver {
    string name;
public:
    Investor(const string& n) : name(n) {}
    void update(const string& stock, double price) override {
        cout << name << " notified: " << stock << " = $" << price << endl;
    }
};

Ex6:
class Pizza {
public:
    virtual string getDescription() const = 0;
    virtual double getCost() const = 0;
    virtual ~Pizza() = default;
};

class BasePizza : public Pizza {
public:
    string getDescription() const override { return "Pizza"; }
    double getCost() const override { return 8.0; }
};

class ToppingDecorator : public Pizza {
protected:
    unique_ptr<Pizza> pizza;
public:
    ToppingDecorator(unique_ptr<Pizza> p) : pizza(move(p)) {}
};

class CheeseDecorator : public ToppingDecorator {
public:
    using ToppingDecorator::ToppingDecorator;
    string getDescription() const override {
        return pizza->getDescription() + " + Cheese";
    }
    double getCost() const override { return pizza->getCost() + 1.5; }
};

class PepperoniDecorator : public ToppingDecorator {
public:
    using ToppingDecorator::ToppingDecorator;
    string getDescription() const override {
        return pizza->getDescription() + " + Pepperoni";
    }
    double getCost() const override { return pizza->getCost() + 2.0; }
};
*/
Exercises - C++ Tutorial | DeepML