Facade Pattern 이란?
Facade Pattern은 소프트웨어 디자인 패턴 중 하나로, 복잡한 서브 시스템을 일련의 인터페이스에 대한 통합된 인터페이스를 제공하는 디자인이다. Facade는 High-level 인터페이스를 정의하여 서브 시스템을 더 쉽게 사용할 수 있도록 만든다. 다시 말해서, 서브 시스템이 어떻게 구현되고 동작하는지는 몰라도 된다.
Facade Pattern의 구조
Facade 패턴은 크게 3가지 요소로 구성됩니다.
- Facade: 클라이언트에서 사용될 high-level 인터페이스를 제공하는 클래스.
- Subsystems: 실제 기능을 구현하는 클래스. Facade에서 여기서 구현된 세부 기능을 제공하기 위해 이 클래스들을 사용.
- Client: Facade를 사용하는 클래스.
클래스 다이어그램으로 표현하면 다음과 같습니다.
위 다이어그램은 클라이언트가 여러 서브 시스템과 직접 상호작용하지 않고 Facade를 통해 이루어짐을 보여준다.
다시 한번 시퀀스 다이어그램으로 보면,
클라이언트는 Facade에 요청을 보내고, Facade는 필요한 서브시스템들과 통신하여 클라이언트가 원하는 결과를 생성한다. 즉, 클라이언트는 이 과정에서 서브시스템들의 존재를 알 필요가 없는 것.
Facade Pattern 예제
프린터, 스캐너, 팩스 등 여러 기능을 가진 복합기(All-in-one Printer)를 구현해보자.
먼저 Facade 패턴을 적용하지 않은 코드는 아래와 같다.
# Complex subsystems
class Printer:
def print_document(self, document):
print(f"Printing {document}")
class Scanner:
def scan(self, document):
print(f"Scanning {document}")
class Fax:
def fax(self, document):
print(f"Faxing {document}")
# Client
printer = Printer()
printer.print("Document1")
scanner = Scanner()
scanner.scan("Document2")
fax = Fax()
fax.fax("Document3")
Facade 패턴을 적용하지 않은 위 코드에서는 클라이언트가 각 기능을 사용하기 위해 직접 서브시스템 객체를 생성하고 메서드를 호출해야 한다. 만약 서브 시스템의 복잡도가 증가하거나 새로운 기능이 추가된다면 클라이언트 코드의 복잡도도 함께 증가하게 된다.
이제 Facade 패턴을 적용해 보자.
# Complex subsystems
class Printer:
def print_document(self, document):
print(f"Printing {document}")
class Scanner:
def scan(self, document):
print(f"Scanning {document}")
class Fax:
def fax(self, document):
print(f"Faxing {document}")
# Facade
class AllInOnePrinter:
def __init__(self):
self.printer = Printer()
self.scanner = Scanner()
self.fax = Fax()
def print(self, document):
self.printer.print_document(document)
def scan(self, document):
self.scanner.scan(document)
def fax(self, document):
self.fax.fax(document)
# Client
all_in_one = AllInOnePrinter()
all_in_one.print_document("Document1")
all_in_one.scan("Document2")
all_in_one.fax("Document3")
Facade 패턴을 적용한 후에는 클라이언트 코드가 훨씬 간결하다. 클라이언트는 Facade인 AllInOnePrinter 클래스만 사용하여 복합기의 다양한 기능을 사용할 수 있게 된 것이다. 이처럼 Facade 패턴은 클라이언트가 서브시스템의 복잡성을 알 필요 없이 간단한 인터페이스를 통해 필요한 기능을 사용할 수 있도록 돕는다.
Facade 패턴 적용 시 고려사항
1) 인터페이스 설계
Facade 패턴을 적용할 때 가장 중요한 점은 클라이언트에 제공할 인터페이스를 잘 설계하는 것이다. 서브시스템의 기능 중 클라이언트에 필요한 기능만을 노출해야 하는게 중요하고 너무 많은 기능의 노출은 Facade의 목적을 달성할 수 없다.
2) 서브시스템과의 결합도
Facade는 서브시스템의 기능을 캡슐화하여 클라이언트에 제공하므로, 서브시스템과는 느슨한 결합을 유지해야 한다. 이를 위해 Facade에서는 서브시스템의 구체적인 클래스를 사용하기보다는 인터페이스나 추상 클래스를 사용하는 것이 좋다.
3) 성능 고려
Facade 패턴을 사용하면 클라이언트와 서브시스템 사이에 상호작용을 하는 layer가 하나 추가되는 셈이다. 따라서 성능에 민감한 시스템에서는 Facade 패턴 사용 시 성능 저하가 발생할 수 있는 점을 고려해야 한다.
Facade Pattern의 장단점
장점
- 서브 시스템에 대한 의존성 최소화 가능. 클라이언트는 서브 시스템의 내부 로직을 알 필요 없이 Facade를 통해 필요한 기능을 사용할 수 있다.
- 서브 시스템이 쉽게 사용될 수 있도록 간단한 인터페이스를 제공한다.
- 서브 클래스들의 기능을 캡슐화하여 한 곳에서 관리할 수 있다.
단점
- Facade 클래스가 서브 시스템에 대한 모든 의존성을 가지게 되므로, Facade 클래스가 커지고 복잡해질 수 있다.
- 새로운 기능 추가 시 Facade 클래스 역시 수정이 필요하므로 수정해야 하므로 유지보수 비용이 증가할 수 있다.
언제 Facade Pattern을 사용할까?
- 시스템이 매우 복잡하고 사용하기 어려울 때
- 서브 시스템들 사이의 의존성을 줄이고 싶을 때
- 서브 시스템들을 좀 더 사용하기 쉽게 만들고 싶을 때
'<개인공부> - IT > [Python]' 카테고리의 다른 글
Python (pass, continue, and break) (0) | 2021.07.20 |
---|---|
Subprocess 모듈이용하기 (0) | 2021.04.15 |
Day 9. PyQt5 (Dialogs) (0) | 2021.03.30 |
Day 8. PyQt5 (Actions, Toolbars, Menus) (0) | 2021.03.20 |
Day 7. PyQt5 (Layouts) (0) | 2021.03.19 |