Design Patterns - Kamills-12/2143-OOP GitHub Wiki

Design Patterns

Kade Miller


What Are Design Patterns?

Design patterns are reusable solutions to common problems in software design. Think of them as templates, you don’t copy/paste them, you use the concept when you face similar problems.

They help you write:

  • Clean code
  • Stuff that’s easy to maintain or refactor

3 Main Categories:

Type Purpose
Creational How objects are created
Structural How classes/objects fit together
Behavioral How objects interact and communicate

Creational Patterns:


Factory Method

Let a class decide which subclass to return.

class Enemy {
public:
    virtual void attack() = 0;
};

class Goblin : public Enemy {
public:
    void attack() override {
        cout << "Goblin attacks!" << endl;
    }
};

class Troll : public Enemy {
public:
    void attack() override {
        cout << "Troll smashes!" << endl;
    }
};

class EnemyFactory {
public:
    static Enemy* createEnemy(string type) {
        if (type == "goblin") return new Goblin();
        else return new Troll();
    }
};

int main() {
    Enemy* e = EnemyFactory::createEnemy("goblin");
    e->attack();  // Goblin attacks!
    delete e;
}

### Singleton: 

class GameManager {
private:
    static GameManager* instance;
    GameManager() {}  // private constructor

public:
    static GameManager* getInstance() {
        if (!instance)
            instance = new GameManager();
        return instance;
    }

    void run() {
        cout << "Game running..." << endl;
    }
};

GameManager* GameManager::instance = nullptr;

### Structural Patterns:

class LegacyPrinter {
public:
    void printOld() {
        cout << "Printing from old printer." << endl;
    }
};

class NewPrinter {
public:
    virtual void print() = 0;
};

class PrinterAdapter : public NewPrinter {
    LegacyPrinter* legacy;
public:
    PrinterAdapter(LegacyPrinter* lp) : legacy(lp) {}
    void print() override {
        legacy->printOld();
    }
};

### Observer:

class Observer {
public:
    virtual void update(string message) = 0;
};

class Logger : public Observer {
public:
    void update(string message) override {
        cout << "[LOG]: " << message << endl;
    }
};

class Subject {
    vector<Observer*> observers;
public:
    void subscribe(Observer* obs) {
        observers.push_back(obs);
    }

    void notify(string msg) {
        for (auto obs : observers)
            obs->update(msg);
    }
};

### Strategy:

class AttackStrategy {
public:
    virtual void attack() = 0;
};

class SwordAttack : public AttackStrategy {
public:
    void attack() override {
        cout << "Swinging sword!" << endl;
    }
};

class BowAttack : public AttackStrategy {
public:
    void attack() override {
        cout << "Shooting arrow!" << endl;
    }
};

class Character {
    AttackStrategy* strategy;
public:
    void setStrategy(AttackStrategy* s) {
        strategy = s;
    }

    void performAttack() {
        strategy->attack();
    }
};
⚠️ **GitHub.com Fallback** ⚠️