Facade[Design Pattern]

SnowCat·2023년 3월 10일
0

Design Pattern

목록 보기
11/23
post-thumbnail

의도

  • 퍼사드 패턴 => 라이브러리, 프레임워크, 다른 클래스들의 복잡한 집합에 대한 단순화된 인터페이스를 제공하는 구조 패턴

문제

  • 라이브러리, 프레임워크의 광대한 객체들의 집합을 가지고 코드를 작동시켜야 한다 하자.
  • 이 경우 객체들을 모두 초기화하고, 종속성 관계들을 추적하고, 올바른 순서로 메서드를 실행하는 등의 작업을 수행해야 함 => 코드 유지보수가 어려워짐

해결책

  • 복잡한 하위 시스템에 대한 간단한 인터페이스 제공 필요 => 퍼사드 사용
  • 퍼사드는 라이브러리, 프레임워크, 클래스에서 클라이언트가 필요한 기능들만을 제공하는 방법을 의미함
  • 가령 영상을 인코딩하는 라이브러리를 사용할 때 라이브러리를 직접 사용하는 대신 encode 메서드만이 있는 퍼사드 클래스를 만들고 비디오 변환 라이브러리와 연결하는 방식을 사용할 수 있음

구조

/**
 * 퍼사드 클래스 내부에 모든 서브시스템을 집어넣고 클라이언트에 필요한 기능 메서드를 정의함
 */
class Facade {
    protected subsystem1: Subsystem1;

    protected subsystem2: Subsystem2;

    /**
     * 필요한 서브시스템 가져오기
     */
    constructor(subsystem1?: Subsystem1, subsystem2?: Subsystem2) {
        this.subsystem1 = subsystem1 || new Subsystem1();
        this.subsystem2 = subsystem2 || new Subsystem2();
    }

    /**
     * 필요한 퍼사드 메서드 제작
     */
    public operation(): string {
        let result = 'Facade initializes subsystems:\n';
        result += this.subsystem1.operation1();
        result += this.subsystem2.operation1();
        result += 'Facade orders subsystems to perform the action:\n';
        result += this.subsystem1.operationN();
        result += this.subsystem2.operationZ();

        return result;
    }
}

/**
 * 크기가 큰 복잡한 클래스
 * 메서드는 클라이언트와 직접 동작하지 않고 퍼사드를 경유해 작동하게 됨
 */
class Subsystem1 {
    public operation1(): string {
        return 'Subsystem1: Ready!\n';
    }

    // ...

    public operationN(): string {
        return 'Subsystem1: Go!\n';
    }
}

class Subsystem2 {
    public operation1(): string {
        return 'Subsystem2: Get ready!\n';
    }

    // ...

    public operationZ(): string {
        return 'Subsystem2: Fire!';
    }
}

/**
 * 클라이언트에서 서브시스템 대신 퍼사드 사용
 */
function clientCode(facade: Facade) {
    console.log(facade.operation());
}

const subsystem1 = new Subsystem1();
const subsystem2 = new Subsystem2();
const facade = new Facade(subsystem1, subsystem2);
clientCode(facade);
/*
Facade initializes subsystems:
Subsystem1: Ready!
Subsystem2: Get ready!
Facade orders subsystems to perform the action:
Subsystem1: Go!
Subsystem2: Fire!
*/

적용

  • 복잡한 하위 시스템에 대한 간단한 인터페이스가 필요할 때 사용
    하위 시스템은 점점 복잡해질 가능성이 높기 때문에 사용할 기능들만을 모아서 퍼사드 형식으로 만들어 주는 것이 도움됨
  • 하위 시스템을 계층들로 구성하려는 경우 사용
    비디오 변환 프레임워크가 있고, 이는 오디오, 비디오의 두개 계층으로 나뉜다 해보자.
    이 둘에 대한 각각의 퍼사드를 만들고 각 계층의 클래스들이 퍼사드를 통해 통신하도록 함으로써 하위시스템의 결합도를 줄일 수 있음

구현방법

  1. 하위시스템의 인터페이스보다 더 간단한 인터페이스를 제공하는 것이 가능한지 확인
    인터페이스가 클라이언트 코드를 DB 등에서부터 독립시킨다면 정답
  2. 새 퍼사드 패턴 클레스에서 인터페이스 선언 및 구현
    퍼사드는 클라이언트 호출을 하위 시스템의 적절한 객체로 리다이렉션 시켜주어야 함
  3. 모든 클라이언트 코드가 퍼사드 패턴을 통해서 하위시스템과 통신하도록 함
    하위시스템이 수정되도 이제 퍼사드 패턴만을 수정하게 되면 됨
  4. 퍼사드가 너무 커지면 행동들 일부를 새로운 퍼사드 클래스로 추출

장단점

  • 복잡한 하위 시스템에서 코드 분리 가능
  • 앱에 모든 클래스에 퍼사드가 결합해버릴 우려가 있음

출처:
https://refactoring.guru/ko/design-patterns/facade

profile
냐아아아아아아아아앙

0개의 댓글