cpp
exercises
exercises.cpp⚙️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; }
};
*/