※ CS 스터디/디자인 패턴

3. 전략 패턴 ( strategy pattern )

J 크 2023. 8. 2. 02:30
728x90
반응형

 재미있다~ 

본 게시글은  : 면접을 위한 CS 전공지식 노트 (출판사 : 길벗, 주홍철 지음) 을 참조하여 작성하였습니다. + 구글링


♣ 전략 패턴 ( strategy pattern or policy pattern )?

 실행(런타임) 중에 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행위 디자인 패턴

인스턴스의 행위를 바꾸고 싶은 경우 '직접' 수정하지 않음

-  전략이라고 부르는 '캡슐화한 알고리즘'을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능

 ( 컨텍스트(Context) - 알고리즘을 실행할 때마다 연결된 전략 객체의 메소드를 호출 )

 

♣ 전략 패턴 장점

-  요구 사항이 변경 되었을 때 코드를 변경하지 않고 클래스 추가를 통하여 수정 가능

  ( if-else 문의 추가 등이 아닌 클래스 추가를 통해 새로운 기능 구현)

- 런타임에 전략 변경 가능 (기능 변경)

♣ 전략 패턴 단점

-  요구 사항이 변경 되었을 때 코드를 변경하지 않고 클래스 추가를 통하여 수정 가능

  ( if-else 문의 추가 등이 아닌 클래스 추가를 통해 새로운 기능 구현)

- 클라이언트가 구체적인 전략을 알아야함


♣ 예시 코드

 

package design03_StrategyPattern;

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

// 전략 패턴 (strategy pattern or policy pattern)
// - 객체의 행위를 직접 수정하지 않음
// - 전략이라고 부르는 캡슐화한 알고리즘을 컨텍스트 안에서 바꿔줌.

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;
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCardNumber() {
		return cardNumber;
	}

	public void setCardNumber(String cardNumber) {
		this.cardNumber = cardNumber;
	}

	public String getCvv() {
		return cvv;
	}

	public void setCvv(String cvv) {
		this.cvv = cvv;
	}

	public String getDateOfExpiry() {
		return dateOfExpiry;
	}

	public void setDateOfExpiry(String dateOfExpiry) {
		this.dateOfExpiry = dateOfExpiry;
	}

	@Override
	public void pay(int amount) {
		System.out.println(amount + " paid using KAKAOCard");
	}
	
}

class LUNACardStrategy implements PaymentStrategy {
	private String emailId;
	private String password;
	
	public LUNACardStrategy(String emailId, String password) {
		this.emailId = emailId;
		this.password = password;
	}
	
	public String getEmailId() {
		return emailId;
	}

	public void setEmailId(String emailId) {
		this.emailId = emailId;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Override
	public void pay(int amount) {
		System.out.println(amount + " paid using LUNACard");
	}
}

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

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = 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 patmentMethod) {
		int amount = calculateTotal();
		patmentMethod.pay(amount);
	}
}

public class StrategyPatternTest {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ShoppingCart cart = new ShoppingCart();
		
		Item A = new Item("kundo1A", 100);
		Item B = new Item("kundolB", 300);
		
		cart.addItem(A);
		cart.addItem(B);
		
		// pay by LUNACard
		cart.pay(new LUNACardStrategy("kundo1@example.com", "pukubababo"));
		
		// pay by KAKAOCard
		cart.pay(new KAKAOCardStrategy("Ju hongchul", "123456789", "123", "12/01"));
	}
}

 코드 내 핵심 사항 (동적으로 코드 수정이 아닌 클래스 추가를 통하여 전략 수정 )

1.  PaymentStrategy 라는 인터페이스를 선언하여 pay라는 기능을 전략으로 선택.

2. KAKAOCardStrategy에서는 pay의 전략을 카드 이름, 번호등의 정보를 검사 하는 것으로 선택

3. LunaCardStrategy 에서는 pay의 전략을 이메일 id와 패스워드 검사 하는 것으로 선택

4. 추가로 다른 회사의 카드 pay 방법을 추가하고 싶은 경우, pay를 재정의 하는 클래스를 추가하여 활용 가능

  (Ex. SSAFYCardStrategy을 생성하여 -> pay의 전략을 ssafy 학번 및 지역 정보를 검사하는 것으로 선택)

내일 강의 들을 수 있을까.

 위의 글과 관련하여 추가적인 내용이나 피드백은 언제나 환영입니다 :)