[Design Pattern] Strategy Pattern
11 Jan 2018Strategy Pattern
특정 콘텍스트에서 알고리즘(전략)을 별도로 분리하는 설계 방법
예시 상황
과일 매장에서 상황에 따라 다른 가격 할인 정책을 적용한다.
- 첫 손님 할인
- 덜 신선한 과일 할인
가격 계산 모듈에 할인 정책 구현
public class Calculator {
public int calculator(boolean firstGuest, List<Item> items) {
int sum = 0;
for (Item item: items) {
if (firstGuest) {
sum += (int) (item.getPrice() * 0.9); // 첫 손님 10% 할인
} else if (! item.isFresh()) {
sum += (int) (item.getPrice() * 0.8); // 덜 신선한 과일 20% 할인
} else {
sum += item.getPrice();
}
}
return sum;
}
}
예시의 문제점
- 서로 다른 정책이 한 코드에 섞여 있어, 정책이 추가될수록 코드 수정이 점점 어려워진다.
전략 패턴을 적용한 Calculator의 구현
Calculator 클래스는 생성자를 통해서 사용할 전략 객체를 전달 받아서 사용한다.
public class Calculator {
private DiscountStrategy discountStrategy;
public Calculator(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
public int calculate(List<Item> items) {
int sum = 0;
for (Item item: items) {
sum += discountStrategy.getDiscountPrice(item);
}
return sum;
}
}
Calculator에서 사용하는 전략 인터페이스
public interface DiscountStrategy {
int getDiscountPrice(Item item);
}
DiscountStrategy 인터페이스를 구현한 콘크리트 클래스
public class FirstGuestDiscountStrategy implements DiscountStrategy {
@Override
public int getDiscountPrice(Item item) {
return (int) (item.getPrice() * 0.9);
}
}
Calculator의 클리어언트 Calculator를 사용하는 코드에서 콘크리트 클래스를 생성한다.
public class Client {
private DiscountStrategy discountStrategy;
public void onFirstGuestButtonClick() {
discountStrategy = new FirstGuestDiscountStrategy();
}
public void onLastGuestButtonClick() {
discountStrategy = new LastGuestDiscountStrategy();
}
public void onCalculationButtonClick() {
Calculator calculator = new Calculator(discountStrategy);
int price = calculator.calculate(items);
}
}