본문 바로가기

지식/Computer Science

[디자인 패턴] 전략 패턴 (Strategy Pattern), 정책 패턴 (Policy Pattern)

전략 패턴은 정책 패턴이라고도 불립니다.

객체의 행위를 바꾸고 싶은 경우 직접 수정하지 않고 전략이라고 부르는 캡슐화한 알고리즘을 컨텍스트안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴입니다.

(컨텍스트 : 상황, 맥락, 문맥을 의미, 개발자가 어떠한 작업을 완료하는 데 필요한 모든 관련 정보를 말합니다.)

 

가장 이해가 쉬운 예제로는 쇼핑을 할 때 네이버페이, 카카오페이 등 다양한 방법으로 결제하듯이 결제의 전략만 바꿔서 적용하는 방법입니다.

 

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

interface PaymentStrategy{  // 결제 전략들을 인터페이스로 정의
    public void pay(int amount);
}

class KakaoCardStrategy implements PaymentStrategy{ // 결제 전략 인터페이스를 상속한 카카오카드

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

    public KakaoCardStrategy(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 = " + amount+ " using KakaoCard");
    }
}

class LunaCardStrategy implements PaymentStrategy{ // 결제 전략 인터페이스를 상속한 루나카드
    private String emailId;
    private String password;

    public LunaCardStrategy(String emailId, String password) {
        this.emailId = emailId;
        this.password = password;
    }


    //결제 메서드를 정의
    @Override
    public void pay(int amount) {
        System.out.println("amount = " + amount +" using LunaCard");
    }
}

class Item{  // 아이템 클래스를 정의
    private String name;
    private int price;

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

    //getter
    public String getName(){
        return name;
    }

    //getter
    public int getPrice(){
        return price;
    }
}

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);
    }
}

public class main{
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart(); // 쇼핑 카트 생성

        Item A = new Item("mouse",100); // 아이템 생성
        Item B = new Item("keyboard", 300); // 아이템 생성 2

        cart.addItem(A); // 쇼핑 카트에 아이템 담기
        cart.addItem(B); // 쇼핑 카트에 아이템2 담기

        // LunaCard 전략을 사용하여 결제
        cart.pay(new LunaCardStrategy("email@email.com","password"));

        //KakaoCard 전략을 사용하여 결제
        cart.pay(new KakaoCardStrategy("Wooseok","123456789","123","12/26"));

    }
}

이 코드는 쇼핑 카트에 아이템을 담아서 LunaCard, KakaoCard라는 두 개의 전략으로 결제하는 코드입니다.

 

* 참고 : passport도 전략패턴

passport는 Nodejs에서 인증 모듈을 구현할 때 쓰는 미들웨어 라이브러리입니다.

여러가지 전략을 기반으로 인증할 수 있게 합니다. 서비스 내의 LocalStrategy 전략과 페이스북, 네이버 등 다른 서비스 기반의 인증인 Oauth 전략 등을 지원합니다.

 

참고

[책] 면접을 위한 CS 전공지식 노트