공부하는 블로그

파사드 패턴과 추상 팩토리 패턴 본문

design patterns

파사드 패턴과 추상 팩토리 패턴

devtimothy 2019. 7. 21. 22:50

파사드 패턴

파사드의 뜻은, 건물 출입구의 정면 외벽을 나타내는 말이다. 건축에서 파사드의 궁극적인 목표는 '소통'이라고 한다.

소통이라는 목표와 걸맞게 파사드 소프트웨어 디자인 패턴 역시 소통하는 역할을 한다.

로직을 단순하게 잡는다면 단순하고, 복잡하다면 복잡하게 만들 수 있는 게 파사드 패턴이라고 설명들을 하는 것 같다.

파사드 패턴을 사용한 대표적인 예로는 SLF4J가 있다고 한다. (Simple Logging Facade for Java)

예제를 찾아보았는데 홈시어터 예제가 있었다. 영화를 보려고 하면, 스피커의 음량을 높이고, 팝콘을 튀기고, TV를 켜고, DVD 플레이어가 재생되고를 한번에 할 수 있다는 식의 예제가 있어서 처음에는 파사드 패턴을 공부하면서는 IoT 스마트 스피커 같은건가? 라는 생각을 했었다. 그러나 그것이 아니었다.

다른 예제를 살펴보니, 로봇을 예로 들고 있다.

로봇의 컴포넌트를 만드는 제작자들은 모든 파트를 개별적으로 제어하며 동시에 모든 파트가 협업하도록 한다. 하지만 로봇 사용자들은 '걷기', '뛰기' 등의 간단한 명령만 전송하게 한다.

로봇을 제어하거나 프로그래밍 하고 싶은 사람은 사실 팔이 어떻게 동작하는지, 다리가 어떻게 동작하는지에는 관심이 없다. 명령을 따르는 완전한 로봇을 조작하기를 원한다.

참여 객체

  • 퍼사드: 상위 수준의 인터페이스 집합을 정의하고 서브시스템을 협업하게 만든다.
  • 서브시스템: Facade와 의존관계에 있지만 Facade에 의존하지는 않는다.

핵심은 서브 시스템 간 연결관계, 의존관계를 최소화 (loose coupling) 하고 복잡한 서브시스템에 대한 간략한 인터페이스를 제공하는 데 있다. 또한 시스템과 시스템 내부의 관계와 구조를 명확하고 직관적으로 유지할 수 있다.

메디에이터 패턴과의 차이점?

일단 메디에이터는 행동 디자인 패턴의 범주, 파사드는 구조 디자인 패턴의 범주에 속한다. 두 패턴 모두 복잡한 시스템간의 관계를 단순화 시켜준다.

메인 클래스와 서브 클래스가 있다는 점에서는 비슷한 것 같아보인다. 그러나 Facade 가 단방향이라면 Mediator 는 양방향의 통신에 대해 중간에서 다리역할을 해준다. 이때 Mediator 가 너무 많은 역할을 하게 될 수 가 있는데 경계해야 할 것이다. (출처: https://hamait.tistory.com/869)

중재자 패턴도 기존에 존재하는 클래스의 기능성을 추상화한다는 점에서 퍼사드 패턴과 비슷합니다. 중재자 패턴의 목적은 여러 객체들 사이의 협력 관계를 추상화하여 기능성의 집중화를 막자는 것입니다. 중재자 패턴에 참여하는 객체는 서로를 직접 알지 못하고 단지 중재자를 통해서만 상호작용이 됩니다. 이에 비해 퍼사드는 서브시스템 인터페이스 자체를 추상화하여 사용을 용이하게 하는 목적을 갖습니다. 즉 새로운 기능성을 추가할 수도 없고, 이런 새로운 추가 기능에 대해서는 알 수도 없습니다. (GoF의 디자인 패턴, 264페이지)

구현시 고려할 사항

  • 사용자와 서브시스템 간 결합도 줄이기: 앞서 설명했듯이 로봇을 사용하는 사람은 로봇의 '걷기', '뛰기' 메소드에만 관심이 있지, 팔이 어떻게 동작하는지 내부 원리에는 관심이 없다.
  • 서브시스템 클래스 중 공개할 것과 감출 것: 파사드 클래스는 상태와 연산을, 서브시스템은 클래스를 캡슐화한다.

마치 클래스와 클래스들을 결합해서 더 큰 클래스를 만드는 듯한 느낌을 받는다.

추상 팩토리 패턴

GoF의 디자인 패턴에서 파사드 패턴의 마지막 부분을 보면 관련 패턴으로 추상 팩토리 패턴이 나온다. 파사드와 함께 쓸 수 있단다.

팩토리 메소드 패턴도 있는데, 추상 팩토리 패턴은 구체적인 제품을 지정하지 않고 팩토리 메소드 집합의 인터페이스를 지정한다. 추상 팩토리는 전체 팩토리 교체를 통해 동일한 생산방식을 따르며 서로 다른 제품을 생산할 수 있게 한다.

참여 객체

  • 추상 팩토리: 팩토리의 산업 표준을 정의하여 컴포넌트나 복잡한 제품을 만드는데 필요한 인터페이스를 제공
  • 콘크리트 팩토리: 추상 팩토리가 정의한 인터페이스를 구현하고 구체적인 제품을 만듦
  • 추상 제품: 팩토리가 만들 제품의 인터페이스 정의
  • 콘크리트 제품: 콘크리트 팩토리가 만들 실제 제품
  • 클라이언트: 팩토리 전체에 생산 프로세스를 배치함

구현 방법

추상 팩토리 패턴에서는 클라이언트가 전체 제품 구축을 위해 콘크리트 팩토리와 상호작용함. 하지만 설계 과정에서 제품의 콘크리트 클래스는 클라이언트에서 분리되며, 클라이언트는 해당 제품이 정확히 무엇인지 파악하는 대신 전체적인 형태만 신경 씀.

활용

  • 객체가 생성되거나 구성, 표현되는 방식과 무관하게 시스템을 독립적으로 만들고자 할 때
  • 여러 제품군 중 하나를 택해 시스템을 설정해야 하고, 한번 구성한 제품을 다른 것으로 대체 가능할 때
  • 관련된 제품 객체들이 함께 사용되도록 설계되었고, 이 부분에 대한 제약이 외부에도 지켜지도록 하고자 할 때
  • 제품에 대한 클래스 라이브러리를 제공하고, 그들의 구현이 아닌 인터페이스를 노출시키고자 할 때

결론

  • 추상 팩토리는 전체 제품군을 쉽고 부드럽게 변경 가능하다. (제품 구성을 쉽게 바꿀 수 있다.)

  • 구체적인 클래스를 분리한다. : 팩토리는 객체 생성과정과 책임을 캡슐화한 것이다. 구체적인 구현 클래스가 사용자에게서 분리된다.

  • 제품 사이의 일관성을 증진시킨다.: 하나의 군 안에 속한 제품 객체들이 함께 동작하도록 설계되었을 때, 앱은 한번에 오직 한 군에서 만든 객체를 사용하도록 함으로써 프로그램의 일관성을 갖도록 한다.

  • 새로운 종류의 제품을 제공하기가 어렵다: 한 군의 제품 집합에만 고정되어 있어 새로운 제품을 만들기는 어렵다. 새로운 제품이 만들어지면 팩토리의 구현을 변경해야 한다.

Comments