디자인 패턴
C++로 액터 만들기

새로운 것을 만들어내는 방법과 관련된 패턴
싱글톤 패턴
생성패턴 중의 하나로 게임에서 플레이어 캐릭터처럼 객체가 하나만 존재해야 할 때 객체를 생성, 사용하는 패턴
class Player {
private:
static Player* instance; // 유일한 플레이어 객체를 가리킬 정적 포인터
int level;
// private 생성자: 외부에서 객체 생성 금지
Player() : level(1) {}
public:
// 복사 생성자와 대입 연산자도 삭제 (삭제 대신 private로 만들어도 됨)
Player(const Player&) = delete;
Player& operator=(const Player&) = delete;
// 정적 메서드: 유일한 비행기 인스턴스를 반환
static Player* getInstance() {
if (instance == nullptr) // 없을 때만 생성
instance = new Player();
return instance; // 있다면 있는 것으로 반환
}
void levelUp() { level++; }
void getLevel() const { cout << level << endl; }
};
// 정적 멤버 초기화
Player* Player::instance = nullptr;
int main() {
// 플레이어 새로 생성
Player* player = Player::getInstance();
player->levelUp();
player->getLevel();
// 기존 플레이어를 받음
Player* samePlayer = Player::getInstance();
player->getLevel();
}
객체들의 구조를 어떻게 구성할지가 이 패턴의 주 관심사
데코레이터 패턴
구조패턴 중의 하나로, 기존 객체의 기능을 수정하지 않고, 객체에 새로운 기능을 동적으로 추가하는 디자인 패턴
예를 들어, 에스프레소(기본 커피)에 물을 추가해 아메리카노를 만들고, 우유를 추가해 라떼를 만드는 것처럼, 기능을 계속 추가하면서 객체를 감싸는 구조
단일 책임 원칙(SRP)과 개방-폐쇄 원칙(OCP)을 지키면서 기능 확장성과 유지보수성을 높일 수 있다
구성 요소

// 추상 컴포넌트 (Component)
// 피자 객체의 기본 구조를 정의하는 인터페이스입니다.
class Pizza {
public:
virtual ~Pizza() {}
virtual string getName() const = 0; // 피자의 이름 반환
};
// 구체 컴포넌트 (Concrete Component)
// 기본 피자 클래스 정의
class BasicPizza : public Pizza {
public:
string getName() const {
return "Basic Pizza"; // 기본 피자의 이름
}
};
// 데코레이터 추상 클래스 (Decorator)
// 기존 피자의 기능을 확장하기 위한 데코레이터의 기본 구조를 정의
// - 내부적으로 `Pizza` 객체를 감싸며, 추가적인 기능을 제공
class PizzaDecorator : public Pizza {
protected:
Pizza* pizza; // 기존의 피자 객체를 참조
public:
// 데코레이터는 피자 객체를 받아서 감쌉니다.
PizzaDecorator(Pizza* p) : pizza(p) {}
// 소멸자에서 내부 피자 객체를 삭제
virtual ~PizzaDecorator() {
delete pizza;
}
};
// 구체 데코레이터 (Concrete Decorators)
// 각 토핑 데코레이터는 `PizzaDecorator`를 상속받아 이름을 확장
class CheeseDecorator : public PizzaDecorator {
public:
CheeseDecorator(Pizza* p) : PizzaDecorator(p) {}
string getName() const {
// 기존 피자의 이름에 " + Cheese" 추가
return pizza->getName() + " + Cheese";
}
};
class PepperoniDecorator : public PizzaDecorator {
public:
PepperoniDecorator(Pizza* p) : PizzaDecorator(p) {}
string getName() const {
// 기존 피자의 이름에 " + Pepperoni"를 추가
return pizza->getName() + " + Pepperoni";
}
};
int main() {
// 1. 기본 피자를 생성합니다.
Pizza* pizza = new BasicPizza();
// 2. 치즈 토핑을 추가합니다.
pizza = new CheeseDecorator(pizza);
// 3. 페퍼로니 토핑을 추가합니다.
pizza = new PepperoniDecorator(pizza);
// 5. 최종 피자 정보 출력
cout << "Pizza: " << pizza->getName() << endl;
// 6. 메모리 해제
delete pizza;
}
특정 객체가 변할 때 다른 객체들에 이 상태를 어떻게 전달할지에 대한 패턴
옵저버 패턴
데이터를 관찰하면서 데이터의 변경이 일어날 시 이를 인지하고 그에 맞는 행동을 함

Observer를 클래스 내에 vector로 등록하여, 데이터 변경이 일어날 시 각 옵저버들을 호출하여 함수 실행



public으로 생성시, 헤더파일은 public에, cpp파일은 private에 생성됨.
이러면 프로젝트의 다른 모듈에서도 해당 클래스에 접근 가능
private로 생성 시, 헤더파일/cpp 파일 둘 다 private에 생성됨. 해당 모듈에서만 접근 가능
액터가 생성되었으며, BeginPlay()함수에 UE_LOG함수를 통해 게임 시작 시 log를 출력하게 할 수 있다.

C++ classes/프로젝트이름/Public에 존재. 아래 사진처럼 Enable Live Coding비활성해야 정상 작동함. 이 액터를 레벨에 마우스로 배치해주면 된다
