개발
home
📔

[디자인 패턴] 전략 (Strategy) 패턴

Created
2022/04/07
Tags
Design Pattern
Strategy Pattern
Java
2022-04-07 @이영훈

전략 (Strategy) 패턴

The strategy pattern is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use. - wiki
알고리즘 그룹에서 어떤 알고리즘을 사용할 지 런타임에 선택할 수 있게 해주는 패턴입니다.
DIP (Dependency Inversion Principal)이랑 느낌이 비슷합니다.
전체 소스 코드는 깃헙에서 확인할 수 있습니다.

빵집 할인 예제

고정할인과 퍼센트할인이 있습니다. 빵집이 오늘 오픈을 해서 2천원 할인 이벤트를 했습니다. 그리고 저녁에 마감 때 50% 할인 이벤트를 했습니다.
전체적인 구조는 다음과 같습니다.

빵집 할인 예제 - 코드 작성

우선 할인 전략 인터페이스를 작성합니다
support 함수로 어떤 할인정책을 선택할 지 정합니다
public interface DiscountPolicy { public boolean support(LocalTime time); public int discount(int itemPrice); }
Java
복사
할인 전략 인터페이스를 구현하여 퍼센트 할인 전략고정 할인 전략을 구현합니다
퍼센트 할인 전략입니다.
public class PercentDiscountPolicy implements DiscountPolicy { private final int discountPercent; public PercentDiscountPolicy(int discountPercent) { this.discountPercent = discountPercent; } @Override public boolean support(LocalTime time) { return time.isAfter(LocalTime.of(20, 0, 0)); } @Override public int discount(int itemPrice) { // 퍼센트 할인시 생기는 소수점 자리는 버림 처리 return (int) (itemPrice * discountPercent * 0.01); } }
Java
복사
고정 할인 전략입니다.
public class FixAmountDiscountPolicy implements DiscountPolicy { private final int discountAmount; public FixAmountDiscountPolicy(int discountAmount) { this.discountAmount = discountAmount; } @Override public boolean support(LocalTime time) { return time.isBefore(LocalTime.of(20, 0, 0)); } @Override public int discount(int itemPrice) { return discountAmount; } }
Java
복사
마지막으로 할인 전략을 사용하는 가격 계산기를 만듭니다.
가격 계산기는 DiscountPolicy 인터페이스를 사용하고 구현체를 사용하지 않습니다.
할인 전략 구현체는 런타임에서 넣어서 사용합니다.
️ routing 함수를 통해서 적합한 할인전략을 선택합니다
public class PriceCalculator { private final List<DiscountPolicy> discountPolicies; public PriceCalculator(List<DiscountPolicy> discountPolicies) { this.discountPolicies = discountPolicies; } public int getDiscountedPrice(List<Integer> items) { int totalPrice = items.stream().reduce(0, Integer::sum); DiscountPolicy discountPolicy = routingDiscountPolicy(); int totalDiscount = discountPolicy.discount(totalPrice); return totalPrice - totalDiscount; } // ⭐️ routing 함수를 통해서 적합한 할인전략을 선택합니다 private DiscountPolicy routingDiscountPolicy() { LocalTime now = LocalTime.now(); return discountPolicies.stream() .filter(discountPolicy -> discountPolicy.support(now)) .findFirst() .orElseThrow(() -> new RuntimeException("There is no matching discount policy")); } }
Java
복사

빵집 할인 예제 - 코드 실행

정책을 변경하는 코드가 없어도 시간이 지나면 자동으로 할인 가격 정책이 변경돼서 가격에 반영되는 것을 알 수 있습니다.
import java.util.Arrays; import java.util.List; public class StrategyApplication { public static void main(String[] args) { PriceCalculator priceCalculator = new PriceCalculator(Arrays.asList( new PercentDiscountPolicy(50), new FixAmountDiscountPolicy(2_000) )); List<Integer> itemPrices = Arrays.asList(1000, 2000, 3000); // 🌞 오전: 오픈 기념 2천원 정액할인 (저녁 10시 이전) int morningPrice = priceCalculator.getDiscountedPrice(itemPrices); System.out.println("morningPrice = " + morningPrice); // morningPrice = 4000 // ⌛️ 같은 코드를 시간이 지나서 저녁 10시가 되었다고 가정... // 🌜 저녁: 마감 50% 할인 (저녁 10시 이후) int nightPrice = priceCalculator.getDiscountedPrice(itemPrices); System.out.println("nightPrice = " + nightPrice); // nightPrice = 3000 } }
Java
복사

Ref.