2022. 2. 22. 00:00ㆍCSharp/Advance
복잡한 객체를 단계별로 구성할 수 있는 창작 디자인 패턴
동일한 구성 코드를 사용하여 객체의 다양한 유형과 표현을 생성할 수 있다.
문제
많은 필드와 중첩 개체를 힘들게 단계별로 초기화해야 하는 복잡한 개체를 상상해 보자.
이러한 초기화 코드는 일반적으로 많은 매개변수가 있는 무시무시한 생성자 내부에 묻혀 있다.
또는 더 나쁜: 클라이언트 코드 전체에 흩어져 있다.
집을 예를 들어 객체 를 생성하는 방법을 생각해 보자.
단순한 집 객체
기본 : 벽, 바닥, 문, 창문, 지붕 ( 모두 n개 이상일 수 있다.)
추가 : 뒤뜰, 난방 시스템, 배관 및 전기 배선... 또는 더 크고 밝은 집
가장 간단한 솔루션은 House 클래스를 확장하고 매개변수의 모든 조합을 포함하는 하위 클래스 집합을 만드는 것
이럴 경우 하위 클래스가 기능별로 다수 만들어 질 것이고 스타일 추가는 더 많은 계층 구조를 만들게 된다.
다른 방법은 House 클래스를 제어하는 모든 가능한 매개 변수를 사용 하여 기본 클래스에서 바로 거대한 생성자를 만들 수 있습니다 . 이 접근 방식은 실제로 하위 클래스의 필요성을 제거하지만 또 다른 문제를 생성합니다.
House 별로 필요한 매개변수(기능별로)의 수가 달라서 생성자 호출이 보기 흉해 지고 생성자 관리가 힘들어 진다.
해결책
객체 생성 코드를 추출하여 builders 라고 하는 별도의 객체로 이동
class diagram
앞 강좌에서 AbstractFactory 로 구현한 내용을 Builder 로 변경한 예제
Director
public class Director
{
public IUnitBuilder Builder { get;init;}
public Director(IUnitBuilder builder) => Builder = builder;
public void BuildWeaponOnly() => Builder.BuildWeapon();
public void BuildArmorOnly() => Builder.BuildArmor();
public void BuildFullFeature()
{
Builder.BuildWeapon();
Builder.BuildArmor();
}
}
Parts
public interface IPart { void GetDescription(); }
public interface IWeapon : IPart { }
public class BigSword : IWeapon
{
public void GetDescription() => Console.WriteLine("BigSword");
}
public class PoisonDagger : IWeapon
{
public void GetDescription() => Console.WriteLine("Dagger");
}
public class DoubleDagger : IWeapon
{
public void GetDescription() => Console.WriteLine("DoubleDagger");
}
public interface IArmor : IPart { }
public class PlateArmor : IArmor
{
public void GetDescription() => Console.WriteLine("PlateArmor");
}
public class LeatherArmor : IArmor
{
public void GetDescription() => Console.WriteLine("LeatherArmor");
}
public class ClothArmor : IArmor
{
public void GetDescription() => Console.WriteLine("ClothArmor");
}
Builder
public interface IUnitBuilder
{
public void BuildWeapon();
public void BuildArmor();
public UnitProduct GetUnitProduct();
}
public abstract class AbstractUnitBuilder : IUnitBuilder
{
protected UnitProduct _product { get; set; } = new UnitProduct();
public abstract void BuildArmor();
public abstract void BuildWeapon();
public virtual UnitProduct GetUnitProduct() => _product;
}
public class WarriorBuilder : AbstractUnitBuilder
{
public override void BuildArmor() => _product.Add(new PlateArmor());
public override void BuildWeapon() => _product.Add(new BigSword());
}
public class RogueUnitBuilder : AbstractUnitBuilder
{
public override void BuildArmor() => _product.Add(new LeatherArmor());
public override void BuildWeapon() => _product.Add(new PoisonDagger());
}
public class AssassinBuilder : AbstractUnitBuilder
{
public override void BuildArmor() => _product.Add(new ClothArmor());
public override void BuildWeapon() => _product.Add(new DoubleDagger());
}
Product
public class UnitProduct
{
private List<IPart> _parts = new List<IPart>();
public void Add(IPart part) =>_parts.Add(part);
public void Show()
{
Console.WriteLine("\nUnit Equipments ---------");
foreach (var part in _parts)
part.GetDescription();
}
}
사용
Director director = new Director(new WarriorBuilder());
director.BuildFullFeature();
director.Builder.GetUnitProduct().Show();
director = new Director(new RogueUnitBuilder());
director.BuildFullFeature();
director.Builder.GetUnitProduct().Show();
director = new Director(new AssassinBuilder());
director.BuildFullFeature();
director.Builder.GetUnitProduct().Show();
// output
Unit Equipments ---------
BigSword
PlateArmor
Unit Equipments ---------
Dagger
LeatherArmor
Unit Equipments ---------
DoubleDagger
ClothArmor
관련영상
'CSharp > Advance' 카테고리의 다른 글
Prototype (0) | 2022.02.24 |
---|---|
Factory Method (0) | 2022.02.23 |
Abstract Factory (0) | 2022.02.21 |
Parallel Programming (PLINQ Optimizing and Parallel Class) (0) | 2022.02.18 |
Parallel Programming (PLINQ) (0) | 2022.02.17 |