재우니의 블로그

Builder Pattern

 

Builder Pattern은 다른 creational (제작) 패턴과 달리 Builder 는 제품에 공통 인터페이스가 필요하지 않습니다. 따라서 동일한 제작 프로세스를 사용하여 다양한 제품을 제작할 수 있습니다.

 

다시 말해서, Builder 패턴은 복잡한 객체를 생성하는 과정을 단계별로 나누어 구성할 수 있는 디자인 패턴입니다. 일반적으로 이 패턴은 대상 객체를 만드는 데 필요한 다양한 설정 옵션이 있거나 생성 과정이 복잡한 경우 사용됩니다. 객체에 대한 구성 정보에 따라 생성 결과를 조작하려는 경우에도 사용할 수 있습니다. 

 

 

Builder 패턴의 주요 구성 요소들은 다음과 같습니다.

 

  • Director: Builder를 가리키며, 최종 결과를 생성하는 과정을 제어합니다.
  • Builder: 생성될 객체의 각 부분에 대한 단계별로 인터페이스를 정의합니다.
  • ConcreteBuilder: Builder 인터페이스를 구현한 클래스로, 실제 객체를 생성하는 과정의 로직을 포함합니다.
  • Product: 최종적으로 생성되는 복잡한 객체입니다.

 

 

using System;

// 각 유닛의 공통 기능을 정의할 IUnit 인터페이스
public interface IUnit
{
    string Name { get; }
    int HP { get; }
    int AttackPower { get; }
    void Attack(IUnit enemy);
    void ReceiveDamage(int damage);
}

// Builder 인터페이스를 작성
public interface IUnitBuilder
{
    void SetName(string name);
    void SetHP(int hp);
    void SetAttackPower(int attackPower);
    IUnit Build();
}

public class Terran : IUnit
{
    public string Name { get; set; }
    public int HP { get; set; }
    public int AttackPower { get; set; }

    public void Attack(IUnit enemy)
    {
        enemy.ReceiveDamage(AttackPower);
    }

    public void ReceiveDamage(int damage)
    {
        HP -= damage;
    }
}

public class Protoss : IUnit
{
    public string Name { get; set; }
    public int HP { get; set; }
    public int AttackPower { get; set; }

    public void Attack(IUnit enemy)
    {
        enemy.ReceiveDamage(AttackPower);
    }

    public void ReceiveDamage(int damage)
    {
        HP -= damage;
    }
}

public class TerranBuilder : IUnitBuilder
{
    private Terran _unit;

    public TerranBuilder()
    {
        Reset();
    }

    public void Reset()
    {
        _unit = new Terran();
    }

    public void SetName(string name)
    {
        _unit.Name = name;
    }

    public void SetHP(int hp)
    {
        _unit.HP = hp;
    }

    public void SetAttackPower(int attackPower)
    {
        _unit.AttackPower = attackPower;
    }

    public IUnit Build()
    {
        IUnit builtUnit = _unit;
        Reset();
        return builtUnit;
    }
}

public class ProtossBuilder : IUnitBuilder
{
    private Protoss _unit;

    public ProtossBuilder()
    {
        Reset();
    }

    public void Reset()
    {
        _unit = new Protoss();
    }

    public void SetName(string name)
    {
        _unit.Name = name;
    }

    public void SetHP(int hp)
    {
        _unit.HP = hp;
    }

    public void SetAttackPower(int attackPower)
    {
        _unit.AttackPower = attackPower;
    }

    public IUnit Build()
    {
        IUnit builtUnit = _unit;
        Reset();
        return builtUnit;
    }
}



public class Game
{
    public static void Main(string[] args)
    {
        IUnitBuilder terranBuilder = new TerranBuilder();
        IUnitBuilder protossBuilder = new ProtossBuilder();

        terranBuilder.SetName("Marine");
        terranBuilder.SetHP(40);
        terranBuilder.SetAttackPower(5);
        IUnit terranUnit = terranBuilder.Build();

        protossBuilder.SetName("Zealot");
        protossBuilder.SetHP(60);
        protossBuilder.SetAttackPower(8);
        IUnit protossUnit = protossBuilder.Build();

        // 유닛들이 서로 싸우기 시작합니다.
        while (true)
        {
            terranUnit.Attack(protossUnit);
            if (protossUnit.HP <= 0)
            {
                Console.WriteLine($"{protossUnit.Name} is defeated!");
                break;
            }

            protossUnit.Attack(terranUnit);
            if (terranUnit.HP <= 0)
            {
                Console.WriteLine($"{terranUnit.Name} is defeated!");
                break;
            }
        }
    }
}

 

 

 

Builder 패턴과 Abstract Factory 패턴의 차이점


목적: 

 

Builder 패턴은 복잡한 객체의 생성 과정을 간소화하는 데 사용되며, 이를 통해 생성 결과를 정교하게 조작할 수 있는 유연성을 제공합니다. 반면, Abstract Factory 패턴은 관련 있는 객체 집합을 생성하도록 돕는 역할을 합니다.

 

객체 생성 과정

 

Builder 패턴에서 객체 생성 과정은 단계별로 진행되며, 필요에 따라 구성 정보를 변경할 수 있습니다. 반면, Abstract Factory 패턴에서 객체 생성 로직은 다양한 구체 팩토리에서 정의되며, 관련 객체를 일괄적으로 생성합니다.

 

사용 케이스:

 

Builder 패턴은 객체 생성 과정이 복잡하거나 다양한 설정 옵션이 있는 경우에 사용됩니다. 반면, Abstract Factory 패턴은 연관된 객체 집합을 동일한 주제나 목적으로 생산하고 생성된 객체를 대체하기 쉽게 만드는 경우에 사용됩니다.

 

 

이 두 패턴 모두 서로 다른 상황에서 유용하게 사용됩니다. 따라서 구현하려는 시스템의 요구 사항에 따라 적절한 패턴을 선택하면 코드의 가독성과 유지 관리성을 높일 수 있습니다.

 

 

 

참고 사이트

 

https://refactoring.guru/design-patterns/builder/csharp/example#lang-features

 

Builder in C# / Design Patterns

/ Design Patterns / Builder / C# Builder is a creational design pattern, which allows constructing complex objects step by step. Unlike other creational patterns, Builder doesn’t require products to have a common interface. That makes it possible to prod

refactoring.guru