6. 전략 패턴(Strategy Pattern)
목차
전략 패턴(Strategy Pattern)란?
전략 패턴(Strategy Pattern)은 행동 디자인 패턴 중 하나로, 알고리즘을 클래스로 캡슐화하여, 클라이언트에서 실행 시 적절한 알고리즘을 동적으로 변경할 수 있도록 돕는 패턴입니다. 즉, 어떤 작업을 수행하는 방법을 전략(Strategy)으로 분리하여, 이를 필요에 따라 유연하게 교체할 수 있도록 만드는 구조입니다.
전략 패턴의 특징
- 알고리즘을 클래스로 캡슐화하여, 알고리즘을 실행하는 클래스를 변경하지 않고, 전략을 바꿀 수 있습니다.
- 알고리즘을 독립적으로 변경할 수 있어 유연성과 확장성을 제공합니다.
- 여러 알고리즘을 인터페이스나 추상 클래스를 통해 정의하고, 이를 구체적인 전략 클래스에서 구현합니다.
- 클라이언트는 실행 시점에서 알고리즘을 선택하고 적용할 수 있습니다.
전략 패턴의 구성 요소
전략 패턴은 다음과 같은 구성 요소로 이루어집니다:
- 컨텍스트(Context): 전략을 사용하는 객체입니다. 클라이언트는 이 객체를 통해 특정 전략을 설정하고 실행합니다.
- 전략(Strategy): 알고리즘을 정의하는 인터페이스 또는 추상 클래스입니다. 다양한 알고리즘은 이 전략 인터페이스를 구현하거나 확장하여 정의됩니다.
- 구체적인 전략(Concrete Strategy): 알고리즘을 실제로 구현하는 클래스들입니다. 각기 다른 알고리즘을 이 클래스들에서 구현하여 클라이언트가 필요에 맞는 알고리즘을 선택할 수 있게 합니다.
전략 패턴 예시 (Java)
이번에는 전략 패턴을 사용하여 가격 계산 방식을 다룬 예시를 만들어 보겠습니다. 예를 들어, 고객에게 할인을 적용하는 방식이 여러 가지일 수 있습니다. 이때 전략 패턴을 사용하여 할인 전략을 유연하게 변경할 수 있습니다.
// 전략 인터페이스: 할인 방식 정의
interface DiscountStrategy {
double applyDiscount(double price);
}
// 구체적인 전략 1: 10% 할인
class Discount10Percent implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price * 0.9; // 10% 할인
}
}
// 구체적인 전략 2: 20% 할인
class Discount20Percent implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price * 0.8; // 20% 할인
}
}
// 구체적인 전략 3: 고정 금액 할인
class FixedAmountDiscount implements DiscountStrategy {
@Override
public double applyDiscount(double price) {
return price - 5; // 5달러 할인
}
}
// 컨텍스트 클래스: 할인 전략을 설정하고 적용하는 역할
class ShoppingCart {
private DiscountStrategy discountStrategy; // 할인 전략을 저장
// 할인 전략 설정
public void setDiscountStrategy(DiscountStrategy discountStrategy) {
this.discountStrategy = discountStrategy;
}
// 가격에 할인 전략 적용
public double calculatePrice(double price) {
return discountStrategy.applyDiscount(price);
}
}
public class Main {
public static void main(String[] args) {
ShoppingCart cart = new ShoppingCart();
// 10% 할인 전략 설정
cart.setDiscountStrategy(new Discount10Percent());
System.out.println("Price after 10% discount: " + cart.calculatePrice(100));
// 20% 할인 전략 설정
cart.setDiscountStrategy(new Discount20Percent());
System.out.println("Price after 20% discount: " + cart.calculatePrice(100));
// 고정 금액 할인 전략 설정
cart.setDiscountStrategy(new FixedAmountDiscount());
System.out.println("Price after fixed amount discount: " + cart.calculatePrice(100));
}
}
위 예시에서 DiscountStrategy는 전략 인터페이스로, 다양한 할인 전략들이 이 인터페이스를 구현하고 있습니다. ShoppingCart는 컨텍스트로, 할인 전략을 설정하고, calculatePrice() 메소드를 통해 가격에 해당 할인 전략을 적용합니다. 이렇게 하면 클라이언트는 할인 전략을 실행 시점에 바꿀 수 있습니다.
전략 패턴의 장점
- 유연한 알고리즘 변경: 전략 패턴을 사용하면 알고리즘을 클라이언트 코드에서 독립적으로 관리할 수 있어, 실행 시점에서 필요한 전략을 쉽게 변경할 수 있습니다.
- 클라이언트 코드 간결화: 클라이언트는 구체적인 알고리즘 구현을 알 필요 없이, 전략 객체만 설정하고 사용하면 되므로 코드가 간결해집니다.
- 확장성: 새로운 전략을 추가할 때 기존 코드를 변경할 필요 없이, 새로운 전략 클래스를 추가하여 쉽게 확장할 수 있습니다.
- 결합도 낮춤: 전략 패턴은 알고리즘을 캡슐화하여 실행 시점에 변경할 수 있기 때문에, 알고리즘을 사용하는 클래스와 알고리즘을 구현하는 클래스의 결합도를 낮출 수 있습니다.
전략 패턴의 단점
- 전략 클래스의 수 증가: 각 알고리즘마다 새로운 전략 클래스를 만들어야 하기 때문에, 전략이 많아질수록 클래스 수가 증가하게 됩니다. 이는 관리 측면에서 번거로울 수 있습니다.
- 복잡한 구조: 간단한 알고리즘을 변경할 때도 전략 패턴을 적용하게 되면 코드 구조가 복잡해질 수 있습니다. 너무 많은 전략을 사용하는 경우엔 오히려 과도한 추상화가 될 수 있습니다.
결론
전략 패턴은 알고리즘을 동적으로 교체할 수 있는 유연한 방법을 제공하는 패턴입니다. 알고리즘을 캡슐화하여 클라이언트가 실행 시점에서 전략을 쉽게 선택하고 변경할 수 있게 하며, 유연성과 확장성을 높여줍니다. 특히 다양한 알고리즘을 적용해야 하는 상황에서 유용하게 사용할 수 있습니다.
하지만 너무 많은 전략을 추가하는 경우에는 코드가 복잡해질 수 있으므로, 전략 패턴을 적용할 때는 적절한 범위에서 사용해야 합니다.