패이스 패턴 소개
패이스 패턴은 개발에서 매우 빈번하게 사용되는 패턴 중 하나입니다. 특히 현재 다양한 서드파티 SDK가 주변에 널려있는 환경에서 이러한 SDK는 대부분 패이스 패턴을 사용합니다. 하나의 패이스 클래스를 통해 전체 시스템의 인터페이스를 단일 통합된 고수준 인터페이스로 만들어 사용자의 사용 복잡성을 낮추고, 구현 세부사항을 사용자로부터 숨깁니다. 물론 개발 과정에서 패이스 패턴은 네트워크 모듈, 이미지 로더 모듈 등 API를 캡슐화하는 데에도 널리 사용됩니다. 아마도 여러분은 이미 수없이 패이스 패턴을 사용해왔을지도 모릅니다. 단지 이론적으로 인지하지 못했을 뿐입니다. 이번 장에서는 이론과 실제를 결합하여 패이스 패턴을 이해해 보겠습니다.
패이스 패턴의 정의
하위 시스템의 외부와 내부 간의 통신은 반드시 하나의 통일된 객체를 통해 이루어져야 합니다. 패이스 패턴(Facade Pattern)은 고수준의 인터페이스를 제공하여 하위 시스템을 더 쉽게 사용할 수 있게 만듭니다.
패이스 패턴의 사용 시나리오
- 하나 또는 여러 하위 시스템에 대한 단순 인터페이스를 제공합니다. 하위 시스템은 점점 더 복잡해지고, 심지어 교체될 수도 있습니다. 대부분의 패턴 사용은 더 많고 작은 클래스를 생성합니다. 이러한 하위 시스템은 재사용성이 높을 뿐만 아니라 사용자 정의 및 수정도 쉽습니다. 이러한 변화성은 하위 시스템의 구체적인 구현을 숨기는 것이 중요하게 만듭니다. Facade는 단순하고 통일된 인터페이스를 제공하여 하위 시스템의 구체적인 구현을 숨기고 변화를 격리합니다.
- 계층 구조의 하위 시스템을 구축할 때, 패이스 패턴을 사용하여 각 계층의 진입점을 정의합니다. 하위 시스템 간에 상호 의존성이 있는 경우, Facade 인터페이스를 통해만 통신하도록 하여 하위 시스템 간의 의존성을 단순화할 수 있습니다.
패이스 패턴 예제
간단한 예제를 통해 패이스 패턴을 설명해 보겠습니다. 먼저 3개의 하위 시스템을 정의하겠습니다. 이 3개의 하위 시스템은 함께 작동해야만 특정 작업을 완료할 수 있습니다.
/**
* 첫 번째 하위 시스템
*/
public class SubsystemOne {
public void executeProcessA() {
System.out.println("하위 시스템 1: 프로세스 A 실행");
}
public void executeProcessB() {
System.out.println("하위 시스템 1: 프로세스 B 실행");
}
public void initialize() {
System.out.println("하위 시스템 1: 초기화");
}
}
/**
* 두 번째 하위 시스템
*/
public class SubsystemTwo {
public void validateInput() {
System.out.println("하위 시스템 2: 입력 유효성 검사");
}
public void processData() {
System.out.println("하위 시스템 2: 데이터 처리");
}
public void generateReport() {
System.out.println("하위 시스템 2: 보고서 생성");
}
}
/**
* 세 번째 하위 시스템
*/
public class SubsystemThree {
public void connectDatabase() {
System.out.println("하위 시스템 3: 데이터베이스 연결");
}
public void saveData() {
System.out.println("하위 시스템 3: 데이터 저장");
}
public void disconnectDatabase() {
System.out.println("하위 시스템 3: 데이터베이스 연결 해제");
}
}
이제 이 세 하위 시스템이 함께 작동하여 특정 작업을 완료해야 하는 경우, 다음과 같이 코드를 작성할 수 있습니다:
// 정상적으로 이 세 하위 시스템이 함께 작동해야 하는 경우
public static void executeWithoutFacade() {
SubsystemOne subsystem1 = new SubsystemOne();
SubsystemTwo subsystem2 = new SubsystemTwo();
SubsystemThree subsystem3 = new SubsystemThree();
// 이 하위 시스템들이 함께 작동해야 하는 기능
subsystem1.initialize();
subsystem1.executeProcessA();
subsystem1.executeProcessB();
subsystem2.validateInput();
subsystem2.processData();
subsystem2.generateReport();
subsystem3.connectDatabase();
subsystem3.saveData();
subsystem3.disconnectDatabase();
}
위 코드에서 보듯이, 이렇게 호출하는 것은 매우 복잡하고 오류가 발생하기 쉽습니다. 만약 패이스 패턴을 사용하여 이 하위 시스템들을 캡슐화하고 단일 인터페이스를 통해 접근하면 훨씬 간단해집니다. 다음과 같이 코드를 작성할 수 있습니다:
/**
* 패이스 패턴은 매우 자주 사용되는 구조적 디자인 패턴으로,
* 패이스 역할을 도입하여 클라이언트와 하위 시스템 간의 상호작용을 단순화합니다.
* 복잡한 하위 시스템 호출을 위한 단일 진입점을 제공하여 하위 시스템과 클라이언트 간의 결합도를 낮추고,
* 클라이언트 호출이 매우 편리해집니다.
*/
public class SystemFacade {
private SubsystemOne subsystem1 = new SubsystemOne();
private SubsystemTwo subsystem2 = new SubsystemTwo();
private SubsystemThree subsystem3 = new SubsystemThree();
public void performMainTask() {
// 이 하위 시스템들이 함께 작동해야 하는 기능
subsystem1.initialize();
subsystem1.executeProcessA();
subsystem1.executeProcessB();
subsystem2.validateInput();
subsystem2.processData();
subsystem2.generateReport();
subsystem3.connectDatabase();
subsystem3.saveData();
subsystem3.disconnectDatabase();
}
}
위와 같이 하면, 하나의 패이스 클래스가 단순한 인터페이스를 제공하여 각 하위 시스템의 로직과 상호작용을 숨기고 사용자에게 통합된 고수준 인터페이스를 제공합니다. 사용이 훨씬 간단해지며, 사용자는 내부 변화를 인지할 필요가 없습니다. 이는 시스템을 더 유연하게 만듭니다.