디자인 패턴/생성 패턴

[c#] 게임으로 이해하는 [생성 패턴] 04 - 빌더(Builder)

DoubleAAa 2025. 3. 8. 18:56

Builder를 간단하게 이해해보자!

 

 

RPG 게임에서 캐릭터가 가진 속성을 생각해보자

체력, 방어, 속도, 마나게이지 뿐만 아니라 가지고 있는 기술, 아직 해금되지 않는 기술들도

전부 캐릭터가 가진 속성이다. 이 캐릭터생성자로 만든다고 생각해보자.

 

- 생성자로 캐릭터를 만들 경우

new 캐릭터1("전사", "근접", 100, 50, 20, 150, ...);

 

이런식으로 생성할텐데, 일단 생성자에 너무 많은 매개변수가 포함되고, 속성의 순서를 기억하기가 어렵다!

이 코드를 만든 당사자면 이해할 순 있겠지만 프로그래밍에선 협업이 중요하다!

 

다른 사람이 내 코드를 봤을때 이 코드가 무엇인지 확실히 알아야 되는데 저 생성자 코드만 보고

캐릭터를 만들 때 무슨 속성을 설정할지 단번에 파악할 수 있을까?

 

- Builder 패턴을 적용할경우

Character warrior = new CharacterBuilder()
    .SetName("전사")
    .SetType("근접")
    .SetHealth(100)
    .SetDefense(50)
    .SetSpeed(20)
    .SetMana(150)
    .Build();

 

이 방법은 속성의 순서를 기억할 필요가 없고, 해당 속성이 무엇인지 명확해 보인다!

 


- Builder란 무엇인가?

복잡한 인스턴스를 조립하는 방식!

객체를 생성하는 방법(How) 객체를 구현하는 방법(What)분리하여,
동일한 생성 절차에서 다양한 표현 결과를 만들 수 있도록 하는 패턴이다.

 

복잡한 객체를 생성과 구현을 분리해서 관리해주는 느낌으로 생각하면 된다!


- Builder 패턴을 사용해보자! (c#)

1. 먼저 캐릭터 클래스를 설계한다!

캐릭터는 이름, 직업, 무기, 체력, 마나, 속도 속성이 있다!

    public class PlayerCharacter
    {
        public string Name { get; set; }
        public string Job { get; set; }
        public string Weapon { get; set; }
        public int Health { get; set; }
        public int Mana { get; set; }
        public int Speed { get; set; }

        public void PlayerShow()
        {
            Console.WriteLine($"[캐릭터 생성 완료] 이름: {Name}, 직업: {Job}, 무기: {Weapon}, " +
                $"체력: {Health}, 마나: {Mana}, 속도: {Speed}");
        }
    }

2. 빌더 인터페이스를 정의한다.

    // 빌더 인터페이스
    public interface ICharaBuilder
    {
        ICharaBuilder SetName(string name);
        ICharaBuilder SetJob(string job);
        ICharaBuilder SetWeapon(string weapon);
        ICharaBuilder SetHealth(int health);
        ICharaBuilder SetMana(int mana);
        PlayerCharacter Build();
    }

 


3. 생성하는 방법(How)을 정의한다!

    // 빌더 구현 방법
    public class CharacterBuilder : ICharaBuilder
    {
        private PlayerCharacter player = new PlayerCharacter();

        public ICharaBuilder SetName(string name)
        {
            player.Name = name;
            return this;
        }

        public ICharaBuilder SetJob(string job)
        {
            player.Job = job;
            return this;
        }

        public ICharaBuilder SetWeapon(string weapon)
        {
            player.Weapon = weapon;
            return this;
        }

        public ICharaBuilder SetHealth(int health)
        {
            player.Health = health;
            return this;
        }

        public ICharaBuilder SetMana(int mana)
        {
            player.Mana = mana;
            return this;
        }

        public PlayerCharacter Build()
        {
            return player;
        }
    }

 

생성하는 방법 설계가 끝났다면 이제 구현할 준비가 다 끝났다는 소리다!

마지막으로 Main에서 구현해서 실행시켜보자!


3. Main에서 구현(What)한다!

    internal class Program
    {
        static void Main(string[] args)
        {
            PlayerCharacter player = new CharacterBuilder()
                .SetName("전사")
                .SetJob("Warrior")
                .SetWeapon("대검")
                .SetHealth(150)
                .SetMana(50)
                .Build();

            player.PlayerShow();
        }
    }

 

테스트 결과1


- 어? 속도 (Speed) 속성을 추가해야해요!

추후 게임이 개발되거나 운영할 때 새로운 속성이 필요하는 경우가 발생할 수 있다!

새롭게 추가될 때 기존에 작성했던 코드들을 다 바꿔줘야 하는가? 이러면 너무 힘들다....ㅠㅠ

 

이 부분이 Builder 패턴이 유지보수가 용이하다는 점이다!

Speed 관련된 속성과 메서드만 추가하고 기존에 미리 만들었던 메서드들은 일절 건들지 않기 때문이다! (OCP 법칙)

ICharaBuilder SetSpeed(int speed);

먼저 빌더 인터페이스 부분에 Speed를 추가하고

        public ICharaBuilder SetSpeed(int speed)
        { 
            player.Speed = speed;
            return this;
        }

그 다음 빌더 코드에서 속도 코드를 새로 추가한다!

Main에서 속도 추가하기

마지막으로 Main에서 캐릭터를 생성할 때 속도만 추가하면

 

테스트 결과2

 

이렇게 기존 코드는 건들지 않으면서 속도 속성만 추가된 것을 확인 할 수 있다!

 

 

- 최종 정리

  코드 설명
객체를 생성하는 방법 CharacterBuilder 클래스 객체를 어떻게 생성할지(How)를 정의한다!
객체를 구현하는 방법 new CharacterBuilder().SetName()... 부분 빌더를 사용해서 실제 객체를 구현한다!