챕터 3-1: 디자인 패턴

언리얼 거토
|2025. 1. 6. 19:53

디자인 패턴이란?
반복적으로 등장하는 개발 문제를 해결하기 위한 일반화된 솔루션.

 

디자인 패턴의 분류

  1. 생성 패턴(Creational Patterns)
    • 객체 생성과 관련된 패턴.
    • 예: 싱글톤 패턴
  2. 구조 패턴(Structural Patterns)
    • 객체 간의 관계를 구성하는 패턴.
    • 예: 데코레이터 패턴
  3. 행동 패턴(Behavioral Patterns)
    • 객체 간의 상호작용을 정의하는 패턴.
    • 예: 옵저버 패턴

싱글톤 패턴 (Singleton Pattern)

목표

  • 객체를 오직 하나만 생성하고 전역적으로 접근 가능하도록 함.

주요 개념

  1. 생성자를 private으로 설정하여 외부에서 객체 생성을 제한.
  2. getInstance() 메서드를 통해 유일한 인스턴스에 접근.

코드 예제

#include <iostream>
using namespace std;

class Airplane {
private:
    static Airplane* instance; // 유일한 인스턴스를 가리키는 정적 포인터
    int positionX;             // X 좌표
    int positionY;             // Y 좌표

    Airplane() : positionX(0), positionY(0) { // private 생성자
        cout << "Airplane Created at (" << positionX << ", " << positionY << ")" << endl;
    }

public:
    // 복사 방지: 복사 생성자와 대입 연산자 삭제
    Airplane(const Airplane&) = delete;
    Airplane& operator=(const Airplane&) = delete;

    // 유일한 인스턴스 반환
    static Airplane* getInstance() {
        if (instance == nullptr) { // 아직 생성되지 않았다면
            instance = new Airplane();
        }
        return instance;
    }

    void move(int deltaX, int deltaY) {
        positionX += deltaX;
        positionY += deltaY;
        cout << "Airplane moved to (" << positionX << ", " << positionY << ")" << endl;
    }

    void getPosition() const {
        cout << "Airplane Position: (" << positionX << ", " << positionY << ")" << endl;
    }
};

Airplane* Airplane::instance = nullptr;

int main() {
    Airplane* airplane = Airplane::getInstance();
    airplane->move(10, 20);
    airplane->getPosition();

    Airplane* sameAirplane = Airplane::getInstance();
    sameAirplane->move(-5, 10);
    sameAirplane->getPosition();

    return 0;
}

코드 설명

  • static 포인터로 유일한 객체를 관리.
  • getInstance()에서 처음 호출 시 객체를 생성하고 이후에는 동일한 객체를 반환.
  • 장점: 자원을 효율적으로 관리.
  • 단점: 멀티스레드 환경에서는 동기화 필요.

데코레이터 패턴 (Decorator Pattern)

목표

  • 객체의 기능을 동적으로 확장하거나 변경할 수 있도록 함.

주요 개념

  1. 기본 컴포넌트: 핵심 기능을 가진 클래스.
  2. 데코레이터 클래스: 기존 객체를 감싸 추가 기능을 제공.

코드 예제

#include <iostream>
#include <string>
using namespace std;

// 기본 피자 클래스
class Pizza {
public:
    virtual ~Pizza() {}
    virtual string getName() const = 0;
    virtual double getPrice() const = 0;
};

class BasicPizza : public Pizza {
public:
    string getName() const { return "Basic Pizza"; }
    double getPrice() const { return 5.0; }
};

class PizzaDecorator : public Pizza {
protected:
    Pizza* pizza;
public:
    PizzaDecorator(Pizza* p) : pizza(p) {}
    virtual ~PizzaDecorator() { delete pizza; }
};

class CheeseDecorator : public PizzaDecorator {
public:
    CheeseDecorator(Pizza* p) : PizzaDecorator(p) {}
    string getName() const { return pizza->getName() + " + Cheese"; }
    double getPrice() const { return pizza->getPrice() + 1.5; }
};

class PepperoniDecorator : public PizzaDecorator {
public:
    PepperoniDecorator(Pizza* p) : PizzaDecorator(p) {}
    string getName() const { return pizza->getName() + " + Pepperoni"; }
    double getPrice() const { return pizza->getPrice() + 2.0; }
};

int main() {
    Pizza* pizza = new BasicPizza();
    pizza = new CheeseDecorator(pizza);
    pizza = new PepperoniDecorator(pizza);

    cout << "Pizza: " << pizza->getName() << endl;
    cout << "Price: $" << pizza->getPrice() << endl;

    delete pizza;
    return 0;
}

코드 설명

  • PizzaDecorator가 Pizza 객체를 감싸 동적으로 기능 추가.
  • 장점: 기존 코드를 수정하지 않고도 기능 확장 가능.

옵저버 패턴 (Observer Pattern)

목표

  • 객체 상태가 변경되면, 이를 관찰하는 다른 객체들에게 자동으로 알림.

주요 개념

  1. Subject: 상태를 관리하며, 관찰자를 등록 및 관리.
  2. Observer: Subject의 상태 변경을 감지.

코드 예제

#include <iostream>
#include <vector>
using namespace std;

class Observer {
public:
    virtual void update(int data) = 0;
};

class ExcelSheet {
private:
    vector<Observer*> observers;
    int data;
public:
    void attach(Observer* observer) {
        observers.push_back(observer);
    }
    void setData(int newData) {
        data = newData;
        for (Observer* obs : observers) obs->update(data);
    }
};

class BarChart : public Observer {
public:
    void update(int data) {
        cout << "BarChart updated with data: " << data << endl;
    }
};

int main() {
    ExcelSheet sheet;
    BarChart barChart;
    sheet.attach(&barChart);

    sheet.setData(5);
    return 0;
}

코드 설명

  • ExcelSheet에서 데이터 변경 시 모든 Observer가 알림을 받음.
  • 장점: 느슨한 결합으로 객체 간 관계 관리.

'TIL > C++' 카테고리의 다른 글

Unreal Engine에서 Tick 사용법  (0) 2025.01.08
챕터 3-2: Unreal Engine 기본 개념  (2) 2025.01.07
챕터 2-4: 객체지향적 설계  (1) 2025.01.03
챕터 2-3 : STL 기초  (1) 2025.01.02
챕터 2-2 : 템플릿  (1) 2024.12.31