반복자(Iterator) 패턴, 빌더(Builder) 패턴

김영웅·2025년 3월 6일

반복자 패턴

반복자 패턴은 내부 구조를 노출하지 않고, 컬렉션의 요소들을 하나씩 순회(traverse)할 수 있도록 하는 행동(Behavioral) 디자인 패턴이다.
STL의 컨테니어들에 항상 들어가있다.

자료구조마다 순회 방식이 다를 수 있다. (예:) 트리는 깊이 우선 탐색(DFS)과 넓이 우선 탐색(BFS) 등 여러 순회 방식이 있다.)

특정 컬렉션을 순회할 때 내부 구조에 직접 접근할 수 있게 된다면, 컬렉션이 변경될 때 마다 클라이언트 코드도 함께 수정해야 하므로 결합도가 높아진다는 문제가 있다.

반복자들은 보통 다음 요소를 가져오는 메서드, 순회가 끝났는지 확인하는 메서드 등을 포함한 인터페이스를 구현한다.
예를 들어 아래처럼 함수를 구현할 수 있다.

bool HasNext() : 다음 요소가 존재하는가?
T Next() : 다음 요소를 가져오고, 내부적으로 포인터(현재 위치)를 한 칸 전진


반복자 인터페이스(Iterator Interface)

template <typename T>
class IIterator
{
	bool HasNext();
	T* Next();
};

위에서 말한대로 Interface를 구현한다.
HaseNext가 true라면 Next로 다음 요소에 접근하는 방식


컬렉션 인터페이스(Collection Interface)

template <typename T>
class IAggregate
{
	IIterator<T> CreateIterator();
};

CreateIterator() : 이 메서드를 통해 컬렉션에 맞는 반복자를 생성(또는 반환)한다.

주의할 점은, 반복자 반환 타입이 IIterator<T> 라는 점이다.
이로써, 컬렉션 구현체가 무엇이든, 클라이언트는 반복자 인터페이스만 보고 순회할 수 있다.


빌더 패턴


빌더(Builder) 패턴은 복잡한 객체의 생성 로직을 객체 내부나 거대한 생성자 대신, 별도의 빌더 객체로 캡슐화하여, 다음을 가능하게한다.

  • 단계별(점진적) 생성

    • 객체를 만들 때 필요한 여러 단계(벽 짓기, 문 설치, 창문 설치 등)를 순차적으로 호출하여 완성해 나갈 수 있음
    • 필요한 것만 호출해 생성할 수 있음. ex) 테라스를 추가한다던가

  • 동일한 생성 과정을 통해 여러 표현을 지원

    • 같은 빌더 인터페이스를 가진 다른 구상 빌더로 교체하면, 전혀 다른 객체도 만들 수 있음
    • 예: CarBuilder가 스포츠카를 만들 수도, SUV를 만들 수도 있음 (옵션/단계 호출 방식만 다름)

  • (옵션) 디렉터(Director)
    • 객체를 어떻게 조합할지를 별도 클래스(디렉터)에 맡길 수 있음
    • 같은 빌더라도, 디렉터가 호출하는 단계 순서만 바꿔도 결과물이 달라짐
    • 클라이언트는 디렉터에게 “이 빌더 써서 이 제품 만들어줘”라고만 말하면 되고, 세부 생성 로직은 디렉터와 빌더가 처리
    • 제작 대행 같은 느낌이다.

class Character
{
public:
	float hp;
	float damage;
	string job;
	string weapon;
};

이 캐릭터 클래스를 빌더로 만든다고 해보자
현재는 너무 간단해서 빌더까지 필요 없겠지만 Builder를 만든다고 생각해보자


class CharacterBuilder
{
private:
	Character* character;

public:
	void Reset()
	{
		character = new Character();
	}

	void SetHp(float hp)
	{
		character->hp = hp;
	}

	void SetDamage(float damage)
	{
		character->damage = damage;
	}

	void SetJob(string job)
	{
		character->job = job;
	}

	void SetWeapon(string weapon)
	{
		character->weapon = weapon;
	}

	Character* GetResult()
	{
		return character;
	}
};

다음과 같이 빌더를 만들었다면
아래와 같이 사용 가능하다.

int main()
{
	CharacterBuilder builder;

	builder.Reset();
	builder.SetJob("전사");
	builder.SetHp(100);
	builder.SetDamage(10);
	builder.SetWeapon("장검");
	
	Character* warrior = builder.GetResult();
}

이런 식으로 순차적으로 구성을 쌓아 제작할 수 있다.

profile
게임 프로그래머

0개의 댓글