내배캠 TIL

[내배캠 TIL 251224] C++ 디자인 패턴 (구조 패턴)

xodn246 2025. 12. 24. 20:12

  구조 패턴 (데코레이 패턴)

      피자 만들기 예제 - 피자에 토핑을 동적으로 추가할 수 있도록 하며 토핑은 이름과 추가 비용을 가지도록 하는 에제이다.

#include <iostream>
#include <string>

using namespace std;

// ** 추상 컴포넌트 : Pizza **
// - 피자 객체의 기본 구조를 정의하는 인터페이스이다.
// - 모든 피자는 이름('getName') 과 가격 ('getPrice')을 가져야 한다.
class Pizza {
 public:
    virtual ~Pizza(){}
    virtual string getName() const = 0;     // 피자의 이름 반환
    virtual double getPrice() const = 0;    // 피자의 가격 반환
};

// ** 구체 컴포넌트 (Concrete Component) : BasicPizza **
// - 기본 피자 클래스이다.
// - 피자의 기본 베이스(이름과 가격)를 구현한다.
class BasicPizza : public Pizza {
 public:
     string getName() const {
         return "Basic Pizza";      // 기본 피자의 이름
    }
     double getPrice() const {
        return 5.0;     // 기본 피자의 가격
    }
};

// ** 데코레이터 추상 클래스 (Decorator) : PizzaDecorator **
// - 기존 피자의 기능을 확장하기 위한 데코레이터의 기본 구조를 정의한다.
// - 내부적으로 'Pizza' 객체를 감싸며, 이름과 가격에 추가적인 기능을 제공한다.
class PizzaDecorator : public Pizza {
 protected:
    Pizza* pizza;   // 기존 피자 객체를 참조한다.
 public:
    // 데코레이터는 피자 객체를 받아서 감싼다.
    PizzaDecorator(Pizza* p) : pizza(p) {}

    // 소멸자 내부 피자 객체를 삭제한다.
    virtual ~PizzaDecorator() {
        delete pizza;
    }
};

// ** 구체 데코레이터 (Concrete Decorators) : Cheese, Pepperoni, Olive **
// - 각각의 토핑 데코레이터는 'PizzaDecorator' 를 상속받아 이름과 가격을 확장한다.

// 치즈 토핑 데코레이터
class CheeseDecorator : public PizzaDecorator {
 public:
    CheeseDecorator(Pizza* p) : PizzaDecorator(p) {}
    string getName() const {
        return pizza -> getName() + " + Cheese";    // 기존 피자의 이름에 " + Cheese"  를 추가
    }
    double getPrice() const {
        return pizza -> getPrice() + 1.5;       // 기존 피자의 가격에 치즈 추가 비용 1.5를 더함
    }
};

// 페퍼로니 데코레이터
class PepperoniDecorator : public PizzaDecorator {
public:
    PepperoniDecorator(Pizza* p) : PizzaDecorator(p) {}
    string getName() const {
        return pizza->getName() + " + Pepperoni";    // 기존 피자의 이름에 " + Pepperoni"  를 추가
    }
    double getPrice() const {
        return pizza->getPrice() + 2.0;       // 기존 피자의 가격에 치즈 추가 비용 1.5를 더함
    }
};

// 올리브 데코레이터
class OliveDecorator : public PizzaDecorator {
public:
    OliveDecorator(Pizza* p) : PizzaDecorator(p) {}
    string getName() const {
        return pizza->getName() + " + Olive";    // 기존 피자의 이름에 " + Olive"  를 추가
    }
    double getPrice() const {
        return pizza->getPrice() + 0.7;       // 기존 피자의 가격에 치즈 추가 비용 1.5를 더함
    }
};

// ** 클라이언트 코드 **
// - 피자와 데코레이터를 조합하여 최종 피자를 생성하고, 정보를 출력한다.
int main() {
    // 1. 기본 피자 생성
    Pizza* pizza = new BasicPizza();

    // 2. 치즈 토핑을 추가
    pizza = new CheeseDecorator(pizza);

    // 3. 페퍼로니 토핑을 추가
    pizza = new PepperoniDecorator(pizza);

    // 4. 올리브 토핑을 추가
    pizza = new OliveDecorator(pizza);

    // 5. 최종 피자 정보 출력
    cout << "Pizza : " << pizza->getName() << endl;     // 피자의 이름 출력
    cout << "Price : $" << pizza->getPrice() << endl;     // 피자의 가격 출력

    // 6. 메모리 해제
    delete pizza;

    return 0;
}