전략 패턴(strategy pattern)
전략 패턴은 정책 패턴(policy pattern)이라고도 하며, 객체의 행위를 바꾸고 싶은 경우에 직접 수정하지 않고 "전략"이라고 부르는 "캡슐화된 알고리즘"을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴이다.
비즈니스 로직을 인터페이스로 만들고, 해당 인터페이스를 구현한 클래스를 사용하도록 만드는 것이라고 생각하면 된다.
우선 Java 코드를 이용한 기본 예제로 알아보고, 추가로 Spring에서 어떻게 전략 패턴을 사용하는지 알아보자.
Java 기본 예제
예제로 알아보자.
interface : Payment
public interface Payment {
void pay(int amount);
}
구현체 1 : KakaoCardPayment
interface Payment를 구현한 클래스이다. KakaoCard로 Payment를 진행하는 방법이다.
public class KakaoCardPayment implements Payment{
private String platform;
private String cardNumber;
public KakaoCardPayment(String cardNumber) {
this.platform = "KAKAO";
this.cardNumber = cardNumber;
}
@Override
public void pay(int amount) {
System.out.println("pay amount : " + amount);
System.out.println("platform : " + this.platform + " | card number : " + this.cardNumber);
}
}
구현체 2 : NaverCardPayment
interface Payment를 구현한 클래스이다. NaverCard로 Payment를 진행하는 방법이다.
public class NaverCardPayment implements Payment{
private String platform;
private String cardNumber;
public NaverCardPayment(String cardNumber) {
this.platform = "NAVER";
this.cardNumber = cardNumber;
}
@Override
public void pay(int amount) {
System.out.println("pay amount : " + amount);
System.out.println("platform : " + this.platform + " | card number : " + this.cardNumber);
}
}
Item과 ShoppingCart
ShoppingCart에 Item을 여러 개 담고, ShoppingCart.pay() 메서드에서 결제 카드 종류를 정한다.
class Item {
public String name;
public int price;
public Item(String name, int price) {
this.name = name;
this.price = price;
}
}
class ShoppingCart {
List<Item> itemList;
public ShoppingCart() {
this.itemList = new ArrayList<>();
}
public void addItem(Item item){
this.itemList.add(item);
}
public int getTotalPrice(){
return itemList.stream().mapToInt(i -> i.price).sum();
}
public void pay(Payment payment){
int amount = getTotalPrice();
payment.pay(amount);
}
}
Main
ShoppingCart.pay(Payment payment)의 매개변수로 Payment를 구현한 KakaoCardPayment , NaverCardPayment 두가지 방법 모두 선택할 수 있다.
public class PaymentMain {
public static void main(String[] args) {
ShoppingCart shoppingCart = new ShoppingCart();
Item item1 = new Item("item1", 1000); //item 1 생성
Item item2 = new Item("item2", 2000); //item 2 생성
//item 들을 shoppingCart에 추가
shoppingCart.addItem(item1);
shoppingCart.addItem(item2);
//두가지 방법으로 Pay
System.out.println("=== Kakao card ===");
shoppingCart.pay(new KakaoCardPayment("1234-1234-1234-1234"));
System.out.println();
System.out.println("=== Naver card ===");
shoppingCart.pay(new NaverCardPayment("4321-4321-4321-4321"));
}
}
출력
=== Kakao card ===
pay amount : 3000
platform : KAKAO | card number : 1234-1234-1234-1234
=== Naver card ===
pay amount : 3000
platform : NAVER | card number : 4321-4321-4321-4321
Spring 의존성 주입 예제
SpringFramework에서의 전략 패턴
스프링에서는 여러 컴포넌트를 @Bean으로 등록하고, 의존성을 주입받아서 사용한다.
객체의 행위 또는 방식을 변경할 가능성이 있는 클래스를 interface로 만들고, 그 구현체를 Bean으로 등록한다.
주문을 담당하는 OrderService가 있다.
현재는 방법 A를 이용해서 주문을 하지만, 추후에 방법이 변경될 가능성이 있다.
이때, OrderService를 interface로 만들고 원하는 방법으로 구현한 클래스만 Bean으로 등록하면 된다.
interface OrderService
public interface OrderService {
void order();
}
방법 1 : MethodAOrderService
@Service
public class MethodAOrderService implements OrderService{
@Override
public void order() {
//방법 A로 저장 로직 구현
}
}
방법 2 : MethodBOrderService
public class MethodBOrderService implements OrderService{
@Override
public void order() {
//방법 B로 저장 로직 구현
}
}
@Configuration에서 MethodA와 MethodB 중의 하나만 Bean으로 등록하거나,
MethodA와 MethodB 둘중의 하나에만 @Service(@Component) 어노테이션을 붙이면 해당 클래스만 Bean으로 등록되게 된다.
Controller에서는 변경할 필요 없이 Bean으로 등록된 OrderService 구현체를 주입받아서 사용하게 된다.
Controller
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public ResponseEntity<?> order(){
String result = orderService.order();
return ResponseEntity.ok(result);
}
}
'컴퓨터 공학 > 프로그래밍 이론' 카테고리의 다른 글
[CS] SOLID : 객체지향 설계 5 원칙 (0) | 2024.02.02 |
---|---|
[CS] 객체지향 4대 특성(캡슐화, 상속, 다형성, 추상화) (0) | 2024.02.02 |
[Spring Boot] DispatcherServlet - 스프링부트의 동작 구조 (0) | 2024.01.22 |
[Spring / 스프링 부트 핵심 가이드] 디자인 패턴 정리 (0) | 2023.10.01 |
[ComputerScience / 디자인 패턴] 브릿지 패턴(Bridge Pattern, 가교 패턴) (0) | 2023.10.01 |