Facade

2022. 3. 10. 00:00CSharp/Design Pattern

반응형

라이브러리, 프레임워크 또는 기타 복잡한 클래스 집합에 대한 단순화된 인터페이스를 제공하는 구조적 디자인 패턴

 

전화로 주문하기

https://refactoring.guru/design-patterns/facade

 

복잡한 프레임워크에 속하는 여러 개체들을 이용하여  코드를 초기화 하고 작동시켜야 한다고 가정해보자

아래와 같은 과정을 모든 개체에 해 주어야 한다.

 

  • 올바른 순서로 개체 초기화 
  • 개체간 종속성을 추적
  • 올바른 순서로 메서드를 실행

 

결과적으로 클래스의 비즈니스 논리가 타사 프레임워크 클래스의 구현 세부 정보와 밀접하게 연결되어 이해하고 유지 관리하기가 어렵다. 

 

이럴 경우 facade 패턴을 통해 문제를 해결 한다. 

 

class diagram

https://refactoring.guru/design-patterns/facade

 

 

어느때 사용해야 하는가?

 

복잡한 하위 시스템에 대한 제한적이지만 간단한 인터페이스가 필요한 경우

하위 시스템을 계층으로 구성하려는 경우

 

주요장점

패턴의 이점을 최대한 활용하려면 모든 클라이언트 코드가 파사드를 통해서만 하위 시스템과 통신하도록 한다.

이제 클라이언트 코드는 하위 시스템 코드의 변경 사항으로부터 보호된다. 

예를 들어, 서브시스템이 새 버전으로 업그레이드되면 파사드의 코드만 수정하면 된다.

 

 

전사, 도적, 암살자 가 하나의 파티를 이루었고

해당 파티가 한번에 attack 을 하는 과정을 구현 하고 싶다고 하자

각 직업을 초기화 하고 무기를 정하고 attack 을 해야 한다.

이것을 client 에서 각각을 처리 하면 향후  도적의 무기가 바뀌었다던지

또는 암살자의 공격력이 변경되었다던지 할때  client 를 직접 수정해야 한다. 

이부분을 facade 를 통해 해결해 보자.

 

일반적인 직업과 일반적인 무기 (앞에서 계속 사용했었던) 

사용방법을 모르면 상당히 복잡할 수 있다. 

앞에서 사용했던 Decorator 도 추가되어 있다. 

public interface IWeapon
{
    void Attack();
}

public class BastardSword : IWeapon
{
    public void Attack() => Console.WriteLine("대검으로 공격");
}
public class Dagger : IWeapon
{
    public void Attack() => Console.WriteLine("단검으로 공격");
}


public abstract class WeaponDecorator : IWeapon
{
    public abstract void Attack();
}

public class Poison : WeaponDecorator
{
    private readonly IWeapon _weapon;

    public Poison(IWeapon weapon)=> _weapon = weapon;

    public override void Attack()
    {
        Console.Write("독묻은 ");  
        _weapon.Attack() ;
    }
}

public class Spike : WeaponDecorator
{
    private readonly IWeapon _weapon;

    public Spike(IWeapon weapon) => _weapon = weapon;

    public override void Attack()
    {
        Console.Write("대못박힌 ");
        _weapon.Attack();
    }
}

public abstract class Unit
{
    protected IWeapon _weapon;
    public Unit(IWeapon weapon) => _weapon = weapon;
    public abstract void Attack();
}

public class Warrior : Unit
{
    public Warrior(IWeapon weapon) : base(weapon) { }
    public override void Attack()
    {
        Console.Write("전사가 ");
        _weapon.Attack();
    }
}

public class Rogue : Unit
{
    public Rogue(IWeapon weapon) : base(weapon) { }
    public override void Attack()
    {
        Console.Write("도적이 ");
        _weapon.Attack();
    }
}

public class Assassin : Unit
{
    public Assassin(IWeapon weapon) : base(weapon) { }
    public override void Attack()
    {
        Console.Write("암살자가 ");
        _weapon.Attack();
    }
}

위 직업 및 무기 들을 사용하기 위한 warrior party facade

public class WarriorPartyFacade
{
    private List<Unit> _units = new List<Unit>();
    public WarriorPartyFacade()
    {
        IWeapon weapon = new Spike(new BastardSword());
        Unit warrior = new Warrior(weapon);

        IWeapon weapon2 = new Poison(new Spike(new Dagger()));
        Unit rogue = new Rogue(weapon2);

        IWeapon weapon3 = new Spike(new Dagger());
        Unit assassin = new Assassin(weapon3);

        _units.Add(warrior);
        _units.Add(rogue);
        _units.Add(assassin);
    }

    public void Attack()
    {
        foreach (var unit in _units)
            unit.Attack();
    }
}

사용법

WarriorPartyFacade party = new WarriorPartyFacade();
party.Attack();
// output
전사가 대못박힌 대검으로 공격
도적이 독묻은 대못박힌 단검으로 공격
암살자가 대못박힌 단검으로 공격

 

관련영상

https://youtu.be/8z5T36AcocQ

 

 

 

반응형

'CSharp > Design Pattern' 카테고리의 다른 글

Proxy  (0) 2022.03.11
Flyweight  (0) 2022.03.11
Decorator  (0) 2022.03.09
Composite  (0) 2022.03.08
Bridge  (0) 2022.03.07