1. 개요
소프트웨어 개발을 하다 보면 알고리즘이나 동작 방식을 상황에 따라 유연하게 변경해야 할 때가 많습니다. Strategy 패턴은 이러한 문제를 해결하기 위해 고안된 디자인 패턴으로, 알고리즘을 캡슐화하여 서로 교체 가능하도록 만드는 것을 목표로 합니다. 이 글에서는 Strategy 패턴의 개념, C# 구현 예제, 그리고 사용 시 주의할 점을 알아보겠습니다.
2. 개념
Strategy 패턴은 다음과 같은 상황에서 유용합니다:
- 여러 알고리즘 중에서 런타임에 하나를 선택해야 하는 경우.
- 특정 동작을 다른 객체와 독립적으로 교체하거나 확장하고 싶은 경우.
Strategy 패턴의 핵심은 "행동(Behavior)을 객체로 캡슐화"하여 클라이언트 코드에서 알고리즘을 직접 변경하지 않고도 동작을 바꿀 수 있도록 하는 것입니다.
구조는 다음과 같습니다:
- Context: 전략 객체를 사용하는 주요 클래스.
- Strategy: 알고리즘의 인터페이스.
- ConcreteStrategy: 특정 알고리즘을 구현한 클래스.
3. 예제
요구사항
사용자가 할인 정책을 선택할 수 있는 온라인 쇼핑몰을 만든다고 가정합시다. 할인 정책에는 다음이 포함됩니다:
- 기본 할인 없음
- 정률 할인 (10% 할인)
- 정액 할인 (5,000원 할인)
코드 구현
// Strategy 인터페이스
public interface IDiscountStrategy
{
decimal ApplyDiscount(decimal price);
}
// ConcreteStrategy: 기본 할인 없음
public class NoDiscountStrategy : IDiscountStrategy
{
public decimal ApplyDiscount(decimal price)
{
return price;
}
}
// ConcreteStrategy: 정률 할인
public class PercentageDiscountStrategy : IDiscountStrategy
{
private readonly decimal _percentage;
public PercentageDiscountStrategy(decimal percentage)
{
_percentage = percentage;
}
public decimal ApplyDiscount(decimal price)
{
return price - (price * _percentage);
}
}
// ConcreteStrategy: 정액 할인
public class FixedDiscountStrategy : IDiscountStrategy
{
private readonly decimal _discountAmount;
public FixedDiscountStrategy(decimal discountAmount)
{
_discountAmount = discountAmount;
}
public decimal ApplyDiscount(decimal price)
{
return price - _discountAmount;
}
}
// Context 클래스
public class ShoppingCart
{
private IDiscountStrategy _discountStrategy;
public ShoppingCart(IDiscountStrategy discountStrategy)
{
_discountStrategy = discountStrategy;
}
public void SetDiscountStrategy(IDiscountStrategy discountStrategy)
{
_discountStrategy = discountStrategy;
}
public decimal CalculateTotal(decimal price)
{
return _discountStrategy.ApplyDiscount(price);
}
}
// 사용 예
class Program
{
static void Main(string[] args)
{
decimal originalPrice = 50000m;
// 기본 할인 없음
var noDiscount = new ShoppingCart(new NoDiscountStrategy());
Console.WriteLine($"No Discount: {noDiscount.CalculateTotal(originalPrice)}원");
// 10% 정률 할인
var percentageDiscount = new ShoppingCart(new PercentageDiscountStrategy(0.1m));
Console.WriteLine($"10% Discount: {percentageDiscount.CalculateTotal(originalPrice)}원");
// 5,000원 정액 할인
var fixedDiscount = new ShoppingCart(new FixedDiscountStrategy(5000m));
Console.WriteLine($"5,000원 Discount: {fixedDiscount.CalculateTotal(originalPrice)}원");
}
}
4. 주의점: 남용을 피하라
Strategy 패턴은 분명 강력한 도구지만, 모든 경우에 적합하지는 않습니다. 다음 사항을 염두에 두세요:
- 간단한 경우에 복잡도 증가: 너무 간단한 문제를 해결하려고 Strategy 패턴을 사용하면 오히려 코드가 복잡해질 수 있습니다.
- 객체 생성 비용: 많은 전략 객체를 생성하고 교체하는 과정에서 성능에 영향을 줄 수 있습니다.
5. 결론
Strategy 패턴은 다양한 알고리즘을 유연하게 사용할 수 있도록 해주는 강력한 디자인 패턴입니다. 특히, 런타임에 동작 방식을 변경해야 하거나 코드의 가독성과 확장성을 높이고 싶을 때 유용합니다. 하지만 과도한 사용은 피해야 하며, 상황에 맞는지 신중히 검토해야 합니다.
6. 관련 링크
다이어그램
반응형
'Workspace > Design Pattern' 카테고리의 다른 글
어댑터 패턴 (Adapter Pattern): 호환되지 않는 인터페이스 연결하기 (0) | 2025.01.22 |
---|---|
데코레이터 패턴 (Decorator Pattern): 유연한 기능 확장의 비밀 (0) | 2025.01.22 |
옵저버 패턴 (Observer Pattern): 알림을 관리하는 효율적인 방법 (0) | 2025.01.22 |
팩토리 패턴 (Factory Pattern): 객체 생성의 유연함을 더하다 (0) | 2025.01.22 |
싱글톤 패턴 (Singleton Pattern) (0) | 2025.01.22 |