전략 패턴

2020-05-17

Strategy Pattern(전략 패턴)

전략 패턴은 Policy 패턴으로도 알려져 있습니다. 다수의 알고리즘을 정의하고, 클라이언트가 사용할 알고리즘을 파라미터로 전달합니다.

전략 패턴의 가장 좋은 예는 Comparator를 파라미터로 받는 Collections.sort() 함수 입니다. Comparator 인터페이스를 구현을 기반으로 객체가 각기 다른 방법으로 정렬을 합니다.

목적

  • 알고리즘 인터페이스를 정의하고 각 알고리즘을 캡슐화하여 상호 교환 가능하게 만듭니다. 전략패턴을 사용하면 알고리즘을 사용하는 클라이언트에서 알고리즘을 쉽게 변경할 수 있습니다.

예제

인터넷에서 쇼핑을 할 때 결제 방식을 신용카드나 카카오페이를 이용해서 결제를 할 수 있습니다.

먼저 전략 패턴에 사용할 인터페이스를 만들어야 합니다.

PaymentStrategy.java

public interface PaymentStrategy {
    void pay(int amount);
}

그 다음 PaymentStrategy 인터페이스를 구현해서 신용카드 결제와 카카오 결제를 구현 하겠습니다.

CreditCardStrategy.java

public class CreditCardStrategy implements PaymentStrategy {

    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;

    public CreditCardStrategy(String name, String cardNumber, String cvv, String dateOfExpiry) {
        this.name = name;
        this.cardNumber = cardNumber;
        this.cvv = cvv;
        this.dateOfExpiry = dateOfExpiry;
    }

    @Override
    public void pay(int amount) {
        System.out.println("신용카드로 " +amount+ "원 결제했습니다.");
    }
}

KakaoPayStrategy.java

public class KakaoPayStrategy implements PaymentStrategy{

    private String kakaoEmail;
    private String kakaoPassword;

    public KakaoPayStrategy(String kakaoEmail, String kakaoPassword) {
        this.kakaoEmail = kakaoEmail;
        this.kakaoPassword = kakaoPassword;
    }

    @Override
    public void pay(int amount) {
        System.out.println("카카오페이로 " +amount+ "원 결제했습니다.");
    }
}

전략 패턴의 구현은 모두 끝났습니다. 이제 아이템과 장바구니를 구현해서 실제 음식을 사는 것 처럼 테스트를 해보겠습니다.

Item.java

public class Item {

    private String name;
    private int price;

    public Item(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }
}

ShoppingCart.java

import java.util.ArrayList;
import java.util.List;

public class ShoppingCart {
    //아이템의 리스트
    List<Item> items;

    public ShoppingCart(){
        this.items=new ArrayList<Item>();
    }

    public void addItem(Item item){
        this.items.add(item);
    }

    public void removeItem(Item item){
        this.items.remove(item);
    }

    public int calculateTotal(){
        int sum = 0;
        for(Item item : items){
            sum += item.getPrice();
        }
        return sum;
    }

    public void pay(PaymentStrategy paymentMethod){
        int amount = calculateTotal();
        paymentMethod.pay(amount);
    }
}

쇼핑카트 클래스 pay 함수는 PaymentStrategy 인터페이스를 인자로 받으므로 해당 인터페이스를 구현한 클래스가 있어야 합니다.

StrategyTests.java

public class StrategyTests {

    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item item1 = new Item("쿼터파운드치즈버거",5800);
        Item item2 = new Item("콜라 R",1700);

        cart.addItem(item1);
        cart.addItem(item2);

        //카카오페이로 결제
        cart.pay(new KakaoPayStrategy("myemail@example.com", "mypwd"));

        //신용카드로 결제
        cart.pay(new CreditCardStrategy("Donghyeon Min", "1234567890123456", "786", "12/15"));
    }
}

결과

카카오페이로 7500 결제했습니다.
신용카드로 7500 결제했습니다.

UML

정리

  • 전략 패턴은 특정 작업에 관한 여러 개의 알고리즘이 있고, 런타임 시 원하는 알고리즘을 유연하게 적용하고 싶을 때 유용합니다.