[λμμΈν¨ν΄] λ°μ½λ μ΄ν° ν¨ν΄
λ°μ½λ μ΄ν° ν¨ν΄ (Decorator Pattern)
λ°μ½λ μ΄ν° ν¨ν΄μ κ°μ²΄ μ§ν₯ λμμΈ ν¨ν΄ μ€ νλλ‘, κ°μ²΄μ λμ μΌλ‘ μλ‘μ΄ κΈ°λ₯μ μΆκ°ν μ μλ ꡬ쑰λ₯Ό μ 곡ν©λλ€. μ΄ ν¨ν΄μ κΈ°μ‘΄μ ν΄λμ€λ₯Ό μμ νμ§ μκ³ λ κ°μ²΄μ μΆκ°μ μΈ μ± μμ λΆμ¬ν μ μκ² ν΄μ€λλ€. λ°μ½λ μ΄ν° ν¨ν΄μ μμ λμ μ‘°ν©(composition)μ ν΅ν΄ κΈ°λ₯μ νμ₯νλ λ°©λ²μ μ μνλ©°, μ΄λ κ°μ²΄ μ§ν₯ μ€κ³μ κ°λ°©-νμ μμΉ(Open-Closed Principle)μ μ€μνλ λνμ μΈ μμ λλ€.
1. λ°μ½λ μ΄ν° ν¨ν΄μ κΈ°λ³Έ κ°λ
- κ΅¬μ± μμ:
- μ»΄ν¬λνΈ(Component): κΈ°λ³Έ μΈν°νμ΄μ€λ μΆμ ν΄λμ€μ΄λ©°, ꡬ체μ μΈ κ°μ²΄λ€μ΄ μ΄λ₯Ό ꡬνν©λλ€.
- μ½ν¬λ¦¬νΈ μ»΄ν¬λνΈ(Concrete Component): μ€μ κΈ°λ₯μ ꡬνν ν΄λμ€μ λλ€. λ°μ½λ μ΄ν°μ μν΄ μ₯μλ κ°μ²΄μ λλ€.
- λ°μ½λ μ΄ν°(Decorator): Component μΈν°νμ΄μ€λ₯Ό ꡬννλ©°, Concrete Component κ°μ²΄λ₯Ό κ°μΈμ μλ‘μ΄ κΈ°λ₯μ μΆκ°ν©λλ€.
- μ½ν¬λ¦¬νΈ λ°μ½λ μ΄ν°(Concrete Decorator): λ°μ½λ μ΄ν°μ ꡬ체μ μΈ κ΅¬ν체λ‘, μΆκ°μ μΈ κΈ°λ₯μ ꡬννκ³ μ΄λ₯Ό μλ κ°μ²΄μ μμν©λλ€.
- μ₯μ :
- λ°νμμ κ°μ²΄μ μλ‘μ΄ κΈ°λ₯μ λμ μΌλ‘ μΆκ°ν μ μμ΅λλ€.
- μμμ λ¨λ°νμ§ μμΌλ©΄μλ κ°μ²΄μ κΈ°λ₯μ νμ₯ν μ μμ΅λλ€.
- ν΄λμ€ κ³μΈ΅μ 볡μ‘μ±μ μ€μ¬μ€λλ€.
- λ¨μ :
- λ°μ½λ μ΄ν°κ° μ¬λ¬ κ° μ€μ²©λλ©΄ 볡μ‘λκ° μ¦κ°ν μ μμ΅λλ€.
- κ°μ²΄μ ꡬμ±(decorator chain)μ΄ λ³΅μ‘ν΄μ§λ©΄, λλ²κΉ μ΄ μ΄λ €μμ§ μ μμ΅λλ€.
2. λ°μ½λ μ΄ν° ν¨ν΄ μμ
μλ μμ μμλ 컀νΌλ₯Ό λ§λλ μμ€ν μμ λ°μ½λ μ΄ν° ν¨ν΄μ μ μ©ν΄ λ³΄κ² μ΅λλ€. κΈ°λ³Έμ μΈ μ»€νΌ(ConcreteComponent)μ μΆκ°μ μΈ μ¬λ£(μ: μ°μ , μ€ν λ±)λ₯Ό λμ μΌλ‘ μΆκ°νλ κΈ°λ₯μ λ°μ½λ μ΄ν°λ₯Ό ν΅ν΄ ꡬνν©λλ€.(C++)
#include <iostream>
#include <memory>
#include <string>
// Component
class Coffee {
public:
virtual std::string getDescription() const = 0;
virtual double cost() const = 0;
virtual ~Coffee() = default;
};
// ConcreteComponent
class SimpleCoffee : public Coffee {
public:
std::string getDescription() const override {
return "Simple Coffee";
}
double cost() const override {
return 2.0;
}
};
// Decorator
class CoffeeDecorator : public Coffee {
protected:
std::unique_ptr<Coffee> decoratedCoffee;
public:
CoffeeDecorator(std::unique_ptr<Coffee> coffee) : decoratedCoffee(std::move(coffee)) {}
std::string getDescription() const override {
return decoratedCoffee->getDescription();
}
double cost() const override {
return decoratedCoffee->cost();
}
};
// ConcreteDecorator
class MilkDecorator : public CoffeeDecorator {
public:
MilkDecorator(std::unique_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
std::string getDescription() const override {
return decoratedCoffee->getDescription() + ", Milk";
}
double cost() const override {
return decoratedCoffee->cost() + 0.5;
}
};
// ConcreteDecorator
class SugarDecorator : public CoffeeDecorator {
public:
SugarDecorator(std::unique_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
std::string getDescription() const override {
return decoratedCoffee->getDescription() + ", Sugar";
}
double cost() const override {
return decoratedCoffee->cost() + 0.3;
}
};
int main() {
// κΈ°λ³Έ μ»€νΌ μμ±
std::unique_ptr<Coffee> myCoffee = std::make_unique<SimpleCoffee>();
std::cout << myCoffee->getDescription() << " $" << myCoffee->cost() << std::endl;
// μ°μ μΆκ°
myCoffee = std::make_unique<MilkDecorator>(std::move(myCoffee));
std::cout << myCoffee->getDescription() << " $" << myCoffee->cost() << std::endl;
// μ€ν μΆκ°
myCoffee = std::make_unique<SugarDecorator>(std::move(myCoffee));
std::cout << myCoffee->getDescription() << " $" << myCoffee->cost() << std::endl;
// νλ²μ λͺ¨λ μμ±
std::unique_ptr<Coffee> myCoffee2 =
std::make_unique<SugarDecorator>(
std::make_unique<MilkDecorator>(
std::make_unique<SimpleCoffee>()));
std::cout << myCoffee2->getDescription() << " $" << myCoffee2->cost() << std::endl;
return 0;
}
Simple Coffee $2
Simple Coffee, Milk $2.5
Simple Coffee, Milk, Sugar $2.8
Simple Coffee, Milk, Sugar $2.8
3. μ½λ μ€λͺ
- Component: Coffee μΈν°νμ΄μ€λ 컀νΌμ getDescriptionκ³Ό cost λ©μλλ₯Ό μ μν©λλ€.
- ConcreteComponent: SimpleCoffee ν΄λμ€λ κΈ°λ³Έ 컀νΌμ μ€λͺ κ³Ό κ°κ²©μ μ 곡ν©λλ€.
- Decorator: CoffeeDecorator ν΄λμ€λ Coffeeλ₯Ό μμλ°μ 컀νΌλ₯Ό μ₯μνλ μν μ ν©λλ€. μ΄ ν΄λμ€λ ꡬμ±λ μ»€νΌ κ°μ²΄λ₯Ό κ°μ§κ³ μμΌλ©°, λ°μ½λ μ΄ν° ν΄λμ€λ μ΄ κ°μ²΄μ μΆκ°μ μΈ κΈ°λ₯μ λ§λΆμ λλ€.
- ConcreteDecorator: MilkDecoratorμ SugarDecoratorλ CoffeeDecoratorλ₯Ό μμλ°μ μ°μ μ μ€νμ μΆκ°νλ κΈ°λ₯μ ꡬνν©λλ€.
μ΄ μμ μμ 컀νΌμ μ°μ μ μ€νμ μΆκ°νλ©΄μλ, μλμ SimpleCoffee ν΄λμ€λ μμ νμ§ μκ³ μλ‘μ΄ κΈ°λ₯μ μΆκ°ν μ μμμ΅λλ€. μ΄μ²λΌ λ°μ½λ μ΄ν° ν¨ν΄μ κ°μ²΄μ κΈ°λ₯μ λμ μΌλ‘ μΆκ°νλ λ° λ§€μ° μ μ©ν ν¨ν΄μ λλ€.