
전략 패턴
로직을 캡슐화해서 런타임에 교체가 가능하도록 만드는 패턴
상속을 사용하는 것이 아님
런타임에 동작 변경이 가능
예시
public class PaymentService {
public void pay(String paymentType, int amount) {
if(paymentType.equals("CARD")) {
System.out.println("신용카드로 " + amount + "원 결제");
// 카드 결제 로직
// ...
} else if(paymentType.equals("CASH")) {
System.out.println("현금으로 " + amount + "원 결제");
// 현금 결제 로직
// ...
} else if(paymentType.equals("KAKAO")) {
System.out.println("카카오페이로 " + amount + "원 결제");
// 카카오페이 로직
// ...
} else if(paymentType.equals("TOSS")) {
System.out.println("토스로 " + amount + "원 결제");
// 토스 로직
// ...
} else if(paymentType.equals("NAVER")) {
System.out.println("네이버페이로 " + amount + "원 결제");
// 네이버페이 로직
// ...
}
}
}이런 상황은 if-else에 종속되어 런타임에 수단을 변경할 수가 없음
무엇보다 SOLID 원칙 위반
→ OCP 위반, 클래스를 새로운 기능 추가시 추가가 아님
수정된 예시
// 신용카드 결제 전략
public class CardPayment implements PaymentStrategy {
private String cardNumber;
public CardPayment(String cardNumber) {
this.cardNumber = cardNumber;
}
@Override
public void pay(int amount) {
System.out.println("신용카드(" + cardNumber + ")로 " + amount + "원 결제");
// 카드 결제 API 호출
}
}
// 카카오페이 전략
public class KakaoPayment implements PaymentStrategy {
private String phoneNumber;
public KakaoPayment(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
@Override
public void pay(int amount) {
System.out.println("카카오페이(" + phoneNumber + ")로 " + amount + "원 결제");
// 카카오페이 API 호출
}
}
// 토스 결제 전략
public class TossPayment implements PaymentStrategy {
private String accountNumber;
public TossPayment(String accountNumber) {
this.accountNumber = accountNumber;
}
@Override
public void pay(int amount) {
System.out.println("토스(" + accountNumber + ")로 " + amount + "원 결제");
// 토스 API 호출
}
}
// 현금 결제 전략
public class CashPayment implements PaymentStrategy {
@Override
public void pay(int amount) {
System.out.println("현금으로 " + amount + "원 결제");
System.out.println("거스름돈을 확인하세요.");
}
}OCP 만족, 각자의 전략 대로 클래스가 만들어짐
// 수정된 Service 단
public class PaymentService {
private PaymentStrategy paymentStrategy;
// 생성자로 전략 주입
public PaymentService(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
// 런타임에 전략 변경 가능
public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
this.paymentStrategy = paymentStrategy;
}
// 전략 실행
public void processPayment(int amount) {
paymentStrategy.pay(amount);
}
}public class Main {
public static void main(String[] args) {
// 카드 결제
PaymentService service = new PaymentService(
new CardPayment("1234-5678-9012-3456")
);
service.processPayment(50000);
// 출력: 신용카드(1234-5678-9012-3456)로 50000원 결제
// 런타임에 카카오페이로 변경
service.setPaymentStrategy(
new KakaoPayment("010-1234-5678")
);
service.processPayment(30000);
// 출력: 카카오페이(010-1234-5678)로 30000원 결제
// 현금으로 변경
service.setPaymentStrategy(new CashPayment());
service.processPayment(10000);
// 출력: 현금으로 10000원 결제
// 거스름돈을 확인하세요.
}
}예시 2
어떤 게임에서 챔피언을 부활 시키려는 하려하는 상황
모든 챔피언마다 부활 방식을 if-else 로…?
그럼 런타임에선 어떻게 할건데..?
수정된 예시 2
우선 부활 방식을 지정하도록 확장
→ 이 setResurrection은 추후에 실행 중에 재지정 하여 사용도 가능함
Share article