Skip to main content

[Design Pattern] 행동 패턴 4. 빌더 (Builder)




빌더 (Builder) #

빌더

  • 객체를 생성하는 클래스와 표현(조립) 하는 클래스를 분리해서, 동일한 절차를 거치더라도 서로 다른 표현(조립된 완성품) 을 생성하는 방법을 제공한다.



  • 문제점 : 너무 많은 인자를 넘겨야 하는 생성자
public class Moster
{
    string name;
    int age;
    int power;
    int speed;
    // ... 많은 수의 필드들
    
    // 엄청나게 늘어날 가능성이 있는 생성자 인자의 수...
    public Moster(string n, int a, int p, int s) {}
}

class Program
{
    static void Main(string[] args)
    {
        Monster m = new Monster("ScaryFireMonster", 11, 99, 500);
    }
}

  • 해결
public interface IMonsterBuilder 
{ 
    // 각각의 요소를 독립적으로 조립할 수 있게 한다.
    // 이렇게 저렇게 조립한 다양한 결과물들을 만들 수 있다. 
    void BuildName(string n);
    void BuildAge(int a);
    void BuildFire(Fire f);
    void BuildIce(Ice i);
}

public class ScaryMosterBuilder : IMonsterBuilder
{
    Monster monster;
    
    public void BuildName(string n)
    {
        monster.Name = n;
    }
    
    public void BuildAge(int a)
    {
        monster.Age = a;
    }
    
    public void BuildFire(Fire f)
    {
        monster.fire = f;
    }
    
    public void BuildIce(Ice i)
    {
        monster.ice = i;
    }
    
    public Monster GetMonster()
    {
        return monster;
    }
}

public class Director
{
    IBuilder builder;
    
    public void SetBuilder(IBuilder b)
    {
        builder = b;
    }
    
    public void BuildScaryFireMonster()
    {
        // 객체를 생성하는 부분이 이곳에 마련되어 있다.
        // 수많은 인자를 넘겨야 하는 생성자가 없다. 
        // 필요한 것들만 Build 해준다. 
        builder.BuildName("ScaryFireMonster");
        builder.BuildAge(13);
        builder.BuildFire(new Fire());
    }
     
    public void BuildScaryIceMonster()
    {
        builder.BuildName("ScaryIceMonster");
        builder.BuildAge(15);
        builder.BuildIce(new Ice());
    }
}

class Program
{
    static void Main(string[] args)
    {
        var builder = new ScaryMosterBuilder();
        var director = new Director();
        
        director.SetBuilder(builder);
        director.BuildScaryFireMonster();
        
        Monster m = builder.GetMonster();
    }
}



개념적인 예시 #

// 빌더
public interface IBuilder
{
    // 객체를 표현(조립)한다. 
    // 나중에 여러가지를 덧붙일 수 있겠다. 
    void BuildPartA();
    void BuildPartB();
    void BuildPartC();
}

public class ConcreteBuilder : IBuilder
{
    private Product _product = new Product();
    
    public ConcreteBuilder()
    {
        this.Reset();
    }
    
    public void Reset()
    {
        this._product = new Product();
    }
    
    public void BuildPartA()
    {
        this._product.Add("PartA1");
    }
    
    public void BuildPartB()
    {
        this._product.Add("PartB1");
    }
    
    public void BuildPartC()
    {
        this._product.Add("PartC1");
    }
    
    public Product GetProduct()
    {
        Product result = this._product;

        this.Reset();

        return result;
    }
}

// 제품
public class Product
{
    private List<object> _parts = new List<object>();
    
    public void Add(string part)
    {
        _parts.Add(part);
    }
    
    public string ListParts()
    {
        string str = string.Empty;

        for (int i = 0; i < this._parts.Count; i++)
            str += _parts[i] + ", ";
            
        str = str.Remove(str.Length - 2);

        return "Product parts: " + str + "\n";
    }
}

// 디렉터
public class Director
{
    private IBuilder _builder;
    public IBuilder Builder
    {
        set { _builder = value; } 
    }
   
    // 객체를 생성한다. 
    public void BuildMinimalViableProduct()
    {
        this._builder.BuildPartA();
    }
    
    public void BuildFullFeaturedProduct()
    {
        this._builder.BuildPartA();
        this._builder.BuildPartB();
        this._builder.BuildPartC();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var director = new Director();
        
        var builder = new ConcreteBuilder();
        director.Builder = builder;
        
        director.BuildMinimalViableProduct();
        Console.WriteLine(builder.GetProduct().ListParts());

        director.BuildFullFeaturedProduct();
        Console.WriteLine(builder.GetProduct().ListParts());

        // without a Director
        builder.BuildPartA();
        builder.BuildPartC();
        Console.Write(builder.GetProduct().ListParts());
    }
}



References #