본문 바로가기
C++ 개발 일지

231211 [C++][UE] 디자인 (설계)패턴 - 2. 팩토리 메서드 패턴

by the_cat_Soy 2023. 12. 11.

팩토리 메서드 패턴 (Factory Method Pattern):

  • 객체 생성을 추상화(껍데기만) 하여 객체 생성의 구체적인 클래스를 분리
  • 구조체와 데이터 테이블과의 관계와 유사하다! 큰 구조가 있고 내용물이 달라짐 .
  • 콘텐츠적인(ex.연출) 분류가 필요할 경우 클래스보다 블루프린트를 사용하면 좋다.
  • 유연성확장성

 

 

과정 1) Actor Class Unit : 추상화 → 구조(껍데기)만 구성

 

<Header>

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Unit.generated.h"

UCLASS()
class THIRDPERSONTEMPLATE_API AUnit : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AUnit();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Unit")
	void Attack();
	virtual void Attack_Implementation() PURE_VIRTUAL(AUnit::Attack_Implementation);
	/*
	UFUNCTION(BlueprintNativeEvent)
	: 이 매크로는 Unreal Engine에서 블루프린트와 상호작용하는 함수로 정의. 이 함수는 네이티브(c++) 구현과 블루프린트 구현 모두를 가질 수 있음. 블루프린트에서 이 함수를 오버라이드하거나  호출할 수 있음.
	*/

	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Unit")
	void Defend();
	virtual void Defend_Implementation() PURE_VIRTUAL(AUnit::Attack_Implementation);
	/*
	PURE_VIRTUAL(AUnit::Defend_Implementation);
	: 이 부분은 함수의 가상 함수 구현을 정의. PURE_VIRTUAL 매크로는 이 함수가 순수 가상 함수임을 나타냄. 수수 가상 함수는 구현이 없으며 파생 클래스에서 반드시 오버라이드해야함. 따라서, AUnit 클래스를 상속하는 클래스는 Defend_Implementation() 함수를 반드시 구현해야함. 
	*/

};

<cpp>

// Fill out your copyright notice in the Description page of Project Settings.

#include "Unit.h"

// Sets default values
AUnit::AUnit()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AUnit::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AUnit::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

 

과정 2) Unit class에서 상속 받은 Enemy → Unit Class의 추상 함수를 Override 구현

 

<Header>

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Unit.h"
#include "Enemy.generated.h"

/**
 * 
 */
UCLASS()
class THIRDPERSONTEMPLATE_API AEnemy : public AUnit
{
	GENERATED_BODY()

public:
	AEnemy();

	//유닛 클래스의 추상 함수를 오버라이드하여 구현
	virtual void Attack_Implementation() override;
	virtual void Defend_Implementation() override;
};

 

<cpp>

// Fill out your copyright notice in the Description page of Project Settings.

#include "Enemy.h"

AEnemy::AEnemy()
{//생성자 구현

}

void AEnemy::Attack_Implementation()
{
	//적의 공격 기능 구현
	UE_LOG(LogTemp, Warning, TEXT("Enemy is attacking!"));
}

void AEnemy::Defend_Implementation()
{
	//적의 방어 기능 구현
	UE_LOG(LogTemp, Warning, TEXT("Enemy is defending!"));
}

 

과정 3) Enemy를 상속 받은 Goblin 생성 → Enemy Class의 추상 함수를 Override 구현

 

<Header>

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Unit.h"
#include "Enemy.generated.h"

/**
 * 
 */
UCLASS()
class THIRDPERSONTEMPLATE_API AEnemy : public AUnit
{
	GENERATED_BODY()

public:
	AEnemy();

	//유닛 클래스의 추상 함수를 오버라이드하여 구현
	virtual void Attack_Implementation() override;
	virtual void Defend_Implementation() override;
};

 

<cpp>

// Fill out your copyright notice in the Description page of Project Settings.

#include "Goblin.h"

void AGoblin::Attack_Implementation()
{
	//고블린의 공격 기능 구현
	UE_LOG(LogTemp, Warning, TEXT("Enemy is attacking!"));
}

void AGoblin::Defend_Implementation()
{
	//고블린의 방어 기능 구현
	UE_LOG(LogTemp, Warning, TEXT("Enemy is defending!"));
}

 

과정4) 콘텐츠적인 분류가 필요할 경우 클래스보다 블루프린트를 사용

ex) 칼을 들고 있는 고블린, 총을 들고 있는 고블린 등…