software design pattern (tsz. software design patterns)
A legismertebb tervezési minták a Gang of Four (GoF) (Design Patterns: Elements of Reusable Object-Oriented Software) könyvből származnak, amely 23 mintát sorol fel, három kategóriába rendezve:
Célja, hogy egy osztályból csak egy példány létezzen a programban, és ezt globálisan elérhetővé tegye.
C++ példa:
class Singleton {
private:
static Singleton* instance;
Singleton() {}
public:
static Singleton* getInstance() {
if (!instance)
instance = new Singleton();
return instance;
}
};
Singleton* Singleton::instance = nullptr;
Lehetővé teszi az objektumok létrehozásának kiszervezését egy metódusba, amely a példányosítás felelősségét átvállalja.
class Product {
public:
virtual void use() = 0;
};
class ConcreteProduct : public Product {
void use() override { std::cout << "Használat\n"; }
};
class Creator {
public:
virtual Product* createProduct() = 0;
};
class ConcreteCreator : public Creator {
Product* createProduct() override {
return new ConcreteProduct();
}
};
Egy meglévő osztály interfészét átalakítja egy másik, elvárt interfésszé – így nem kompatibilis osztályokat illeszt össze.
class OldInterface {
public:
void specificRequest() { std::cout << "Régi interfész\n"; }
};
class Target {
public:
virtual void request() = 0;
};
class Adapter : public Target {
OldInterface* old;
public:
Adapter(OldInterface* o) : old(o) {}
void request() override {
old->specificRequest();
}
};
Lehetővé teszi, hogy az objektumokat faként szervezzük, ahol az összetett objektumok és az elemek ugyanúgy kezelhetők.
class Component {
public:
virtual void operation() = 0;
};
class Leaf : public Component {
void operation() override { std::cout << "Levél\n"; }
};
class Composite : public Component {
std::vector<Component*> children;
public:
void add(Component* c) { children.push_back(c); }
void operation() override {
for (auto c : children) c->operation();
}
};
Egy objektum állapotváltozását több másik objektum követi, automatikusan értesülnek a változásról.
class Observer {
public:
virtual void update() = 0;
};
class Subject {
std::vector<Observer*> observers;
public:
void attach(Observer* o) { observers.push_back(o); }
void notify() {
for (auto o : observers) o->update();
}
};
class ConcreteObserver : public Observer {
void update() override { std::cout << "Frissítés történt!\n"; }
};
Lehetővé teszi, hogy egy algoritmust családként definiáljunk, és a konkrét implementációkat futásidőben cseréljük.
class Strategy {
public:
virtual void execute() = 0;
};
class ConcreteStrategyA : public Strategy {
void execute() override { std::cout << "Stratégia A\n"; }
};
class Context {
Strategy* strategy;
public:
void setStrategy(Strategy* s) { strategy = s; }
void doAction() { strategy->execute(); }
};
A tervezési minták az objektumorientált elvek mélyebb megértésére építenek:
A tervezési minták nem kötelezőek, de segítenek az alábbi esetekben:
A tervezési minták építőelemek a szoftvertervezéshez. Bár elsőre absztraktnak tűnhetnek, a gyakorlatban időt takarítanak meg, és kódminőséget javítanak. C++ nyelven különösen fontos figyelni az alacsony szintű részletekre, például a memóriakezelésre és a hatékonyságra – a minták viszont abban is segítenek, hogy a struktúra világos és jól dokumentált legyen.