디자인패턴
[디자인패턴] 파사드패턴 & 전략패턴
개바리여리
2025. 9. 29. 23:02
Facade 패턴
복잡한 서브시스템(여러 클래스나 모듈)을 **간단한 인터페이스(파사드)**로 감싸서 클라이언트가 쉽게 사용할 수 있게 해주는 구조 패턴.
다수로 구성되는 서브 시스템을 하나로 묶어주는 Facade 클래스가 존재하는 형태이다.
// 서브시스템 1: 엔진
class Engine {
public void start() {
System.out.println("엔진 가동");
}
}
// 서브시스템 2: 연료펌프
class FuelPump {
public void pump() {
System.out.println("연료 공급");
}
}
// 서브시스템 3: 배터리
class Battery {
public void supplyPower() {
System.out.println("배터리 전원 공급");
}
}
// 서브시스템 4: 점화장치
class Ignition {
public void ignite() {
System.out.println("점화 장치 작동");
}
}
// 파사드 (Facade)
class CarFacade {
private Engine engine;
private FuelPump fuelPump;
private Battery battery;
private Ignition ignition;
public CarFacade() {
this.engine = new Engine();
this.fuelPump = new FuelPump();
this.battery = new Battery();
this.ignition = new Ignition();
}
public void startCar() {
System.out.println("=== 자동차 시동 프로세스 시작 ===");
battery.supplyPower();
fuelPump.pump();
ignition.ignite();
engine.start();
System.out.println("=== 자동차 시동 완료 ===");
}
}
자동차 시동을 거는 과정은 여러 단계가 필요해요.
- 연료 공급 → 엔진 점화 → 배터리 체크 → 시동 모터 구동
클라이언트가 이 모든 클래스를 직접 호출하면 복잡해진다.
CarFacade를 두어 클라이언트는 startCar()만 호출하면 된다
이렇게 함으로써 클라이언트는 세부 클래스가 무엇인지 몰라도 원하는 구성을 가져와서 구현할 수 있다.
전략 패턴 (Strategy Pattern)
특정 작업을 하는 방식(전략)을 여럿 두고 필요에 따라 런타임 환경에 갈아끼울 수 있는 패턴이다.
행위를 캡슐화하여 필요할 때 교체 가능하게 만드는 패턴
- Context(문맥): 전략을 사용하는 쪽 → 실행 시점에 어떤 전략을 쓸지 선택.
- Strategy(전략 인터페이스): 공통된 동작 규약을 정의.
- ConcreteStrategy(구체 전략): 실제 알고리즘/로직을 구현.
if-else 대신 전략 객체를 갈아끼워서 유연성을 확보하는 구조이다.
// 전략 인터페이스
interface PaymentStrategy {
void pay(int amount);
}
// 구체적인 전략들
class CreditCardPayment implements PaymentStrategy {
private String name;
private String cardNumber;
CreditCardPayment(String name, String cardNumber) {
this.name = name;
this.cardNumber = cardNumber;
}
@Override
public void pay(int amount) {
System.out.println(amount + "원을 " + name + "의 CreditCard(" + cardNumber + ")로 지불");
}
}
class PayPalPayment implements PaymentStrategy {
private String email;
PayPalPayment(String email) {
this.email = email;
}
@Override
public void pay(int amount) {
System.out.println(amount + "원을 PayPal(" + email + ")로 지불");
}
}
// Context (전략을 사용하는 쪽)
class ShoppingCart {
private PaymentStrategy paymentStrategy;
// 전략을 바꿀 수 있도록 set 메서드 제공
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
public void checkout(int amount) {
if (paymentStrategy == null) {
System.out.println("결제 수단이 선택되지 않았습니다.");
} else {
paymentStrategy.pay(amount);
}
}
}
// 실행
public class Main {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 전략을 신용카드로 설정
cart.setPaymentStrategy(new CreditCardPayment("홍길동", "1111-2222-3333-4444"));
cart.checkout(10000);
// 전략을 PayPal로 변경
cart.setPaymentStrategy(new PayPalPayment("user@example.com"));
cart.checkout(20000);
}
}
해당 방식은 새로운 방식이 추가되어야 한다면 또 다른 전략 클래스를 만들어 쉽게 확장가능하고
다른 곳에 재사용 하는것도 가능하게 된다.
어떻게 보면 개방-폐쇄 원칙을 준수하는 코드도 작성 할 수 있게 된다.