delegation pattern (tsz. delegation patterns)
A delegáció (delegation) a C++ egyik fontos tervezési mintája, amely lehetővé teszi, hogy egy objektum bizonyos feladatokat egy másik objektumra bízzon. Ez különösen akkor hasznos, ha egy osztály nem szeretné vagy nem tudja teljes mértékben ellátni az adott feladatot, hanem inkább egy másik osztályra ruházza át azt.
A delegáció egy olyan mechanizmus, amelyben egy objektum nem közvetlenül hajt végre egy adott műveletet, hanem egy másik objektumra bízza annak végrehajtását. Ez a minta hasonló az örökléshez, de rugalmasabb, mert nem alá-fölérendeltségi kapcsolatot használ, hanem kompozíciót.
Bár az öröklés egy módja annak, hogy egy osztály viselkedését újrafelhasználjuk, néha problémákhoz vezethet, például túlzott függőségekhez és merev hierarchiákhoz. A delegáció ezzel szemben lehetővé teszi, hogy egy osztály egy másik osztályt használjon anélkül, hogy szorosan összekapcsolódna vele.
#include <iostream>
// Ősosztály
class Logger {
public:
void log(const std::string& message) {
std::cout << "Log: " << message << std::endl;
}
};
// Származtatott osztály
class Application : public Logger {
public:
void run() {
log("Az alkalmazás fut...");
}
};
int main() {
Application app;
app.run();
return 0;
}
Itt az Application örökli a Logger osztályt, így közvetlenül használhatja a log()
függvényt.
#include <iostream>
// Külső osztály
class Logger {
public:
void log(const std::string& message) {
std::cout << "Log: " << message << std::endl;
}
};
// Az Application osztály delegálja a naplózást a Logger osztálynak
class Application {
private:
Logger logger;
public:
void run() {
logger.log("Az alkalmazás fut...");
}
};
int main() {
Application app;
app.run();
return 0;
}
Ebben az esetben az Application osztály nem örökli a Logger osztályt, hanem kompozícióval tartalmaz egy példányt belőle. A log()
hívását így a Logger
objektum végzi el.
A C++11 bevezetett egy újabb típusú delegációt: konstruktor-delegációt, amely lehetővé teszi, hogy egy konstruktor meghívjon egy másik konstruktort ugyanazon osztályon belül.
#include <iostream>
class Person {
private:
std::string name;
int age;
public:
// Alapértelmezett konstruktor
Person() : Person("Ismeretlen", 0) {}
// Teljes konstruktor
Person(const std::string& n, int a) : name(n), age(a) {}
void display() {
std::cout << "Név: " << name << ", Kor: " << age << std::endl;
}
};
int main() {
Person p1; // Az alapértelmezett konstruktor hívja a teljes konstruktort
p1.display();
Person p2("Gábor", 30);
p2.display();
return 0;
}
Ebben a példában az alapértelmezett konstruktor (Person()
) delegálja a munkát a teljes konstruktorra (Person(const std::string&, int)
), így csökkentve a kódszaporulatot és biztosítva az inicializáció következetességét.
A delegáció különösen tervezési minták esetében népszerű, például a Stratégia és a Megfigyelő mintában.
A stratégia minta esetében egy osztály átruház egy adott viselkedést egy másik osztályra, amely később cserélhető.
#include <iostream>
#include <memory>
// Stratégia interfész
class Strategy {
public:
virtual void execute() = 0;
virtual ~Strategy() {}
};
// Konkrét stratégia 1
class ConcreteStrategyA : public Strategy {
public:
void execute() override {
std::cout << "Strategia A végrehajtása" << std::endl;
}
};
// Konkrét stratégia 2
class ConcreteStrategyB : public Strategy {
public:
void execute() override {
std::cout << "Strategia B végrehajtása" << std::endl;
}
};
// Kontextus osztály
class Context {
private:
std::unique_ptr<Strategy> strategy;
public:
Context(std::unique_ptr<Strategy> strat) : strategy(std::move(strat)) {}
void setStrategy(std::unique_ptr<Strategy> strat) {
strategy = std::move(strat);
}
void performTask() {
strategy->execute();
}
};
int main() {
// Stratégia A használata
Context context(std::make_unique<ConcreteStrategyA>());
context.performTask();
// Átváltás Stratégia B-re
context.setStrategy(std::make_unique<ConcreteStrategyB>());
context.performTask();
return 0;
}
Itt a Context osztály nem maga hajt végre egy műveletet, hanem egy Strategy interfészt használ. Ez lehetővé teszi, hogy rugalmasan válasszuk ki a kívánt stratégiát futásidőben.
A delegáció egy hasznos tervezési minta a C++-ban, amely lehetővé teszi a felelősségek szétosztását az osztályok között. Segítségével tisztább, újrafelhasználhatóbb és rugalmasabb kódot írhatunk. Különösen fontos lehet tervezési minták, konstruktor-delegáció és kompozíció alkalmazásakor.
Ha jól használjuk, a delegáció csökkentheti a kód bonyolultságát és növelheti a moduláris tervezés hatékonyságát! 🚀