9.1 느슨한 결합
9.1-1 강한 결합과 느슨한 결합
- 강한 결합(Tight Coupling)
클래스들이 서로 의존성을 가지는 경우.
ex. Card 클래스가 없다면 Person 클래스가 만들어 질 수 없는 경우
Person 클래스는 Card 클래스에 대한 의존성을 가진다고 함.
- 느슨한 결합(Loose Coupling)
실물에 의존하지 말고 추상적 설계에 의존하라.(DIP 원칙)
ex. Person은 왜 Card가 필요한가? 출입을 확인해야 하기 때문.
출입에 관련된 추상적인 설계를 만들어보자.
ICheck를 상속 받은 새로운 카드 인터페이스를 통해 해결하고자 함.
나중에 새로운 Card 클래스가 생성되도, ICheck 인터페이스를 상속 받는 방식.
- 이러한 느슨한 결합 구조는 유지 보수를 손쉽게 만들어줌.
다만, ICheck와 의존성이 떨어지다보니 그곳에서 무슨일이 벌어지는지는 모름.
9.1-2 느슨한 결합의 간편한 구현 - 델리게이트
- 델리게이트는 함수를 오브젝트처럼 관리하는 방식.
- 함수 포인터를 활용한 콜백 함수 방식
가능 하지만 이를 정의하고 사용하는 과정이 꽤나 복잡함.
안정성을 스스로 검증해야하고 C++ 17 규약의 std::bind와 std::function은 느림.
- C#의 델리게이트 키워드의 모방
함수를 마치 개체처럼 다룰 수 있음. 안정적이고 간편하게 선언 가능.
언리얼도 느슨한 결합 구조를 위해 델리게이트를 지원함.
9.1-3 발행 구독 디자인 패턴
- 푸시 형태의 알림을 구현하는데 적합한 디자인 패턴
- 발행자와 구독자로 구분됨.
제작자는 컨텐츠를 생산함.
발행자는 컨텐츠를 배포함.
구독자는 배포된 컨텐츠를 받아서 소비함.
제작자와 구독자는 서로를 몰라도 발행자를 통해 컨텐츠를 생산하고 소비할 수 있음.(느슨한 결합)
- 발행 구독 디자인 패턴의 장점
제작자와 구독자는 서로를 모르기 때문에 느슨한 결합으로 구성됨.
유지 보수가 쉽고 유연하게 활용될 수 있으며 테스트가 쉬워짐.
시스템 스케일을 유연하게 조절할 수 있으며 기능 확장이 용이해짐.
- 언리얼 엔진은 발행 구독 디자인 패턴을 위해 델리게이트 기능을 제공함.
델리게이트의 사전적 의미는 대리자. 즉 위에서 설명한 발행자.
배포는 Broadcast(), 구독은 Add() 함수로 가능함.
9.1-3 언리얼 델리게이트 선언시 고려사항
- 어떤 데이터를 전달하고 받을 것인가
매개변수 자료형과 그 갯수
일대일 전달 / 일대다 전달
- 프로그래밍 환경
C++ 프로그래밍에서만 사용 / C++ 프로그래밍과 블루프린트 프로그래밍 사용
- 어떤 함수와 연결할 것인가
클래스 외부에 설계된 C++ 함수와 연결
전역에 설계된 정적 함수와 연결
언리얼 오브젝트의 멤버 함수와 연결(대부분 이 방식)
9.1-4 언리얼 델리게이트 선언 매크로
DECLARE_{델리게이트유형}_DELEGATE_{함수정보}
- 델리게이트 유형
일대일 + C++ | DECLARE_DELEGATE |
일대다 + C++ | DECLARE_MULTICAST |
일대일 + C++ & 블루프린트 | DECLARE_DYNAMIC |
일대다 + C++ & 블루프린트 | DECLARE_DYNAMIC_MULTICAST |
- 함수 정보
인자 없음 + 반환값 없음 | 공란 (ex. DECLARE_DELEGATE) |
인자 한개 + 반환값 없음 | OneParam (ex. DECLARE_DELEGATE_OneParam) |
인자 세개 + 반환값 있음 (인자는 최대 9개까지 지원함.) |
RetVal_ThreeParams (ex. DECLARE_DELEGATE_RetVal_ThreeParams) |
9.1-5 언리얼 델리게이트 예제
- 학사 정보(CourceInfo)와 학생(Student)가 있음. 시스템에서 학사 정보를 변경하면
알림 구독한 학생들에게 변경 내용을 자동으로 전달하고자 함.
- 새 C++ 클래스 > UObject 부모 클래스 > "CourseInfo" 클래스 생성
<hide/>
// CourseInfo.h
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "CourseInfo.generated.h"
DECLARE_MULTICAST_DELEGATE_TwoParams(FCourseInfoOnChangedSignature, const FString&, const FString&);
UCLASS()
class UNREALDELEGATE_API UCourseInfo : public UObject
{
GENERATED_BODY()
public:
UCourseInfo();
FCourseInfoOnChangedSignature OnChanged;
void ChangeCourseInfo(const FString& InSchoolName, const FString& InNewContents);
private:
FString Contents;
};
<hide/>
// CourseInfo.cpp
#include "CourseInfo.h"
UCourseInfo::UCourseInfo()
{
Contents = TEXT("기존 학사 정보");
}
void UCourseInfo::ChangeCourseInfo(const FString& InSchoolName, const FString& InNewContents)
{
Contents = InNewContents;
UE_LOG(LogTemp, Log, TEXT("[CourseInfo] 학사 정보가 변경되어 알림을 발송합니다."));
OnChanged.Broadcast(InSchoolName, Contents);
}
<hide/>
// Student.h
...
class UNREALDELEGATE_API UStudent : public UPerson, public ILessonInterface
{
...
void GetNotification(const FString& School, const FString& NewCourseInfo);
};
<hide/>
// Student.cpp
...
void UStudent::GetNotification(const FString& School, const FString& NewCourseInfo)
{
UE_LOG(LogTemp, Log, TEXT("[Student] %s님이 %s로부터 받은 메시지 : %s"), *Name, *School, *NewCourseInfo);
}
<hide/>
// MyGameInstance.h
...
class UNREALDELEGATE_API UMyGameInstance : public UGameInstance
{
...
private:
UPROPERTY()
TObjectPtr<class UCourseInfo> CourseInfo;
...
};
<hide/>
// MyGameInstance.cpp
...
#include "CourseInfo.h"
...
void UMyGameInstance::Init()
{
Super::Init();
CourseInfo = NewObject<UCourseInfo>(this);
UE_LOG(LogTemp, Log, TEXT("============================"));
UStudent* Student1 = NewObject<UStudent>();
Student1->SetName(TEXT("학생1"));
UStudent* Student2 = NewObject<UStudent>();
Student2->SetName(TEXT("학생2"));
UStudent* Student3 = NewObject<UStudent>();
Student3->SetName(TEXT("학생3"));
CourseInfo->OnChanged.AddUObject(Student1, &UStudent::GetNotification);
CourseInfo->OnChanged.AddUObject(Student2, &UStudent::GetNotification);
CourseInfo->OnChanged.AddUObject(Student3, &UStudent::GetNotification);
CourseInfo->ChangeCourseInfo(SchoolName, TEXT("변경된 학사 정보"));
UE_LOG(LogTemp, Log, TEXT("============================"));
}
'Unreal > [서적] 언리얼5 이득우님 인프런1' 카테고리의 다른 글
Ch 11. 구조체와 Map (0) | 2023.05.13 |
---|---|
Ch 10. Array and Set (0) | 2023.05.12 |
Ch 08. 컴포지션 (0) | 2023.05.11 |
Ch 07. 언리얼 인터페이스 (0) | 2023.05.11 |
Ch 06. 언리얼 리플렉션 2 (0) | 2023.05.10 |
댓글