소프트웨어 개발 과정에서 코드의 유연성과 재사용성은 매우 중요하다.
이를 위해 객체 지향 프로그래밍에서 다양한 디자인 패턴들이 개발되었는데, 그중에서도 전략 패턴은 유연한 소프트웨어 설계를 구현하는 핵심적인 기법 중 하나이다.
전략 패턴은 알고리즘을 독립적으로 정의하고, 실행 시에 필요한 알고리즘을 동적으로 변경할 수 있는 방법을 제공한다.
전략 패턴
전략 패턴은 알고리즘을 정의하는 인터페이스를 만들고, 이를 구체적인 알고리즘 클래스들로 구현하여 실행 시에 알고리즘들을 변경할 수 있도록 한다. 이를 통해 동일한 작업을 수행하는 여러 알고리즘들을 쉽게 추가하고 변경할 수 있다.
이를 통해 코드의 유연성과 확장성을 크게 향상할 수 있다.
아래와 같은 구조를 가진다.
시나리오는 간단하다.
쇼핑카드에 여러 가지 아이템을 담고 계산을 할 때 우리가 원하는 결제수단으로 동적으로 바꿀 수 있다.
public interface PaymentStrategy {
void pay(int amount);
}
public class KAKAOCardStrategy implements PaymentStrategy{
private String name;
private String cardNumber;
public KAKAOCardStrategy(String name, String cardNumber) {
this.name = name;
this.cardNumber = cardNumber;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using KAKAOCard.");
}
}
public class NAVERPAY implements PaymentStrategy{
private String email;
private String password;
public NAVERPAY(String email, String password) {
this.email = email;
this.password = password;
}
@Override
public void pay(int amount) {
System.out.println(amount + " paid using NAVERPAY");
}
}
KAKAOCard와 NAVERPAY는 PaymentStrategy를 구현하였다.
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;
}
}
import java.util.ArrayList;
import java.util.List;
public class ShoppingCart {
List<Item> items;
public ShoppingCart() {
this.items = new ArrayList<>();
}
public void addItem(Item item) {
this.items.add(item);
}
public void removeItem(Item item) {
this.items.remove(item);
}
public void pay(PaymentStrategy paymentMethod) {
int amount = calculateTotal();
paymentMethod.pay(amount);
}
private int calculateTotal() {
int sum = 0;
for (Item item : items) {
sum += item.getPrice();
}
return sum;
}
}
pay의 매개변수는 다형성을 활용하여 PaymentStrategy를 구현한 어떠한 클래스가 들어와도 상관이 없다.
public class Main {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
Item A = new Item("apple",100);
Item B = new Item("banana",200);
cart.addItem(A);
cart.addItem(B);
cart.pay(new KAKAOCardStrategy("kakao","123"));
// 300 paid using KAKAOCard.
cart.pay(new NAVERPAY("kimtaesoo7@naver.com","1234"));
// 300 paid using NAVERPAY
}
}
cart.pay 부분을 보면 우리가 원하는 결제 수단으로 PaymentStrategy를 구현한 모든 클래스를 사용할 수 있다.
이를 통해 동적으로 우리가 원하는 방법으로 쉽게 바꿀 수 있다.
장단점
장점
- 런타임에 한 객체 내부에서 사용되는 알고리즘들을 교환할 수 있다.
- 알고리즘을 사용하는 코드에서 알고리즘의 구현 세부 정보들을 고립할 수 있다.
- 개방/폐쇄 원칙. 콘텍스트를 변경하지 않고도 새로운 전략들을 도입할 수 있다.
단점
- 알고리즘이 많지 않다면 오히려 인터페이스로 복잡해질 수 있다.
- 클라이언트들은 적절한 전략을 선택할 수 있도록 전략 간의 차이점을 알아야 한다.
정리
- 전략 패턴은 유연성과 확장성을 향상하는 좋은 전략이다.
- 알고리즘을 동적으로 변경할 수 있어서 실행 시 유연한 선택이 가능하다.
- 새로운 알고리즘을 추가하거나 기존 알고리즘을 다른 곳에서도 재사용할 수 있다.
- 또한 알고리즘을 독립적으로 관리하고 변경할 수 있어서 코드의 유지 보수가 용이하다.
'CS' 카테고리의 다른 글
프록시 패턴(Proxy Pattern) (0) | 2023.05.12 |
---|---|
옵저버 패턴(Observer Parttern) (0) | 2023.05.11 |
팩토리 메소드 패턴(Factory Method Pattern) (0) | 2023.04.29 |
싱글톤 패턴(Singleton Pattern) (0) | 2023.04.27 |
컴퓨터 시스템의 구성 (0) | 2023.04.16 |