2) Strategy 패턴: 알고리즘을 런타임에 교체
“알고리즘을 캡슐화하고 교체 가능하게 만듦”
2-1) 문제 상황
// ❌ 할인 정책이 하드코딩됨
public class OrderService {
public int calculateDiscount(Order order, String customerType) {
if (customerType.equals("VIP")) {
return order.getAmount() * 20 / 100; // 20% 할인
} else if (customerType.equals("REGULAR")) {
return order.getAmount() * 10 / 100; // 10% 할인
} else {
return 0;
}
}
}
문제점:
- 새 할인 정책 추가 시 기존 코드 수정
- 할인 로직 재사용 불가
- 테스트 어려움
2-2) Strategy 패턴 적용
// Strategy 인터페이스
public interface DiscountStrategy {
int calculate(int amount);
}
// 구체 전략들
public class VipDiscountStrategy implements DiscountStrategy {
@Override
public int calculate(int amount) {
return amount * 20 / 100;
}
}
public class RegularDiscountStrategy implements DiscountStrategy {
@Override
public int calculate(int amount) {
return amount * 10 / 100;
}
}
public class NoDiscountStrategy implements DiscountStrategy {
@Override
public int calculate(int amount) {
return 0;
}
}
// Context (전략 사용)
public class Order {
private int amount;
private DiscountStrategy discountStrategy;
public Order(int amount, DiscountStrategy discountStrategy) {
this.amount = amount;
this.discountStrategy = discountStrategy;
}
public void setDiscountStrategy(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
public int getFinalAmount() {
int discount = discountStrategy.calculate(amount);
return amount - discount;
}
}
// ✅ 사용
Order vipOrder = new Order(10000, new VipDiscountStrategy());
System.out.println(vipOrder.getFinalAmount()); // 8000
Order regularOrder = new Order(10000, new RegularDiscountStrategy());
System.out.println(regularOrder.getFinalAmount()); // 9000
// 런타임에 전략 변경 가능
vipOrder.setDiscountStrategy(new NoDiscountStrategy());
System.out.println(vipOrder.getFinalAmount()); // 10000
2-3) 실전 예제: 정렬 전략
public interface SortStrategy<T> {
void sort(List<T> list);
}
public class QuickSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
@Override
public void sort(List<T> list) {
// 퀵 정렬 구현
Collections.sort(list);
}
}
public class MergeSortStrategy<T extends Comparable<T>> implements SortStrategy<T> {
@Override
public void sort(List<T> list) {
// 병합 정렬 구현
}
}
public class DataProcessor<T extends Comparable<T>> {
private SortStrategy<T> sortStrategy;
public DataProcessor(SortStrategy<T> sortStrategy) {
this.sortStrategy = sortStrategy;
}
public void process(List<T> data) {
sortStrategy.sort(data);
System.out.println("Sorted: " + data);
}
}
// 사용
List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9);
DataProcessor<Integer> processor = new DataProcessor<>(new QuickSortStrategy<>());
processor.process(numbers);
2-4) Spring에서의 Strategy 패턴
// Strategy 인터페이스
public interface NotificationStrategy {
void send(String message);
}
// 구현체들
@Component("emailNotification")
public class EmailNotificationStrategy implements NotificationStrategy {
@Override
public void send(String message) {
System.out.println("Email: " + message);
}
}
@Component("smsNotification")
public class SmsNotificationStrategy implements NotificationStrategy {
@Override
public void send(String message) {
System.out.println("SMS: " + message);
}
}
// Context
@Service
public class NotificationService {
private final Map<String, NotificationStrategy> strategies;
public NotificationService(List<NotificationStrategy> strategyList) {
this.strategies = strategyList.stream()
.collect(Collectors.toMap(
s -> s.getClass().getSimpleName(),
s -> s
));
}
public void notify(String type, String message) {
NotificationStrategy strategy = strategies.get(type + "NotificationStrategy");
if (strategy != null) {
strategy.send(message);
}
}
}
📚 다음 편: 준비 중입니다.
💬 댓글