서브 시스템의 인터페이스로 통합된 인터페이스를 제공하고 싶을 때, 복잡한 시스템의 부분만 사용하거나 특정 방법으로 인터랙션 할 인터페이스를 제공하는 패턴
보통 라이브러리, 프레임워크와 같은 복잡한 서비스 집합에 대한 단순화된 인터페이스를 제공할 때 사용
1. 다음과 같은 주문, 결제, 배달 서비스를 제공하는 시스템이 있다고 하자.
class Order {
public boolean placeOrder(String product) {
return true;
}
}
class Payment {
public boolean makePayment(String creditCardNumber) {
return true;
}
}
class Delivery {
public boolean arrangeDelivery(String address) {
return true;
}
}
2. 3개의 서비스를 다 이용하기 위한 클라이언트 코드는 다음과 같다.
public class Client {
public static void main(String[] args) {
Order order = new Order();
Payment payment = new Payment();
Delivery delivery = new Delivery();
String product = "DoctorPepper";
String creditCardNumber = "123456789";
String address = "Seoul Jung-gu";
if (!order.placeOrder(product)) {
System.out.println("Order placement failed");
return;
}
if (!payment.makePayment(creditCardNumber)) {
System.out.println("Payment failed");
return;
}
if (!delivery.arrangeDelivery(address)) {
System.out.println("Delivery arrangement failed");
return;
}
System.out.println("Order successful");
}
}
위 상황에서 장바구니(shoppingCart)와 같은 추가 서비스가 등장한다면 그에따라 Client코드는 바뀌게 될 것이고 Client코드를 다시 컴파일해야할 것이다.
복잡한 시스템에 대한 간단한 인터페이스를 제공하는 클래스를 중간에 둔다면? 서비스가 추가 및 변경되어도 Client코드를 바꿀 필요가 없다!
위의 쇼핑 예제로 퍼싸드 패턴을 적용한 코드를 작성하면 다음과 같다.
1. Subsystems
class Order {
public boolean placeOrder(String product) {
return true;
}
}
class Payment {
public boolean makePayment(String creditCardNumber) {
return true;
}
}
class Delivery {
public boolean arrangeDelivery(String address) {
return true;
}
}
문제상황의 Subsystem과 동일하다.
2. Facade
class OnlineShoppingFacade {
private Order order;
private Payment payment;
private Delivery delivery;
public OnlineShoppingFacade() {
order = new Order();
payment = new Payment();
delivery = new Delivery();
}
public boolean placeOrder(String product, String creditCardNumber, String address) {
if (!order.placeOrder(product)) {
System.out.println("Order placement failed");
return false;
}
if (!payment.makePayment(creditCardNumber)) {
System.out.println("Payment failed");
return false;
}
if (!delivery.arrangeDelivery(address)) {
System.out.println("Delivery arrangement failed");
return false;
}
System.out.println("Order successful");
return true;
}
}
Client에 있는 Subsystem객체들을 Facade객체로 옮겨주었고 placeOrder라는 함수로 각 Subsystem의 기능을 사용하도록 한다.
3. Client
public class Client {
public static void main(String[] args) {
OnlineShoppingFacade onlineShopping = new OnlineShoppingFacade();
onlineShopping.placeOrder("DoctorPepper", "123456789", "Seoul Jung-gu");
}
}
문제 상황과 비교하면 Client의 코드가 많이 줄어들었다. Subsystem의 추가되었거나 변경되었다면 Facade객체의 수정을 하면 되기 때문에 Client와의 낮은결합을 형성할 수 있다.
어댑터 패턴을 간단하게 설명하면 서로 호환이 되지 않는 인터페이스를 연결해주는 패턴
이다. 어댑터 패턴과 퍼싸드 패턴은 클라이언트와 다른 클래스 사이에 인터페이스 역할을 하는 클래스를 둔다는 공통점이 있다. 하지만 두 패턴은 사용하는 의도와 구현방법에 차이가 있다.
호환이 되지 않는 인터페이스를 연결
이지만, 퍼싸드 패턴의 의도는 복잡한 서브시스템의 인터페이스를 단순화
이다.