전략 패턴을 활용한 알고리즘 유연성 설계

전략 패턴의 핵심 개념

전략 패턴은 특정 문제에 대한 다양한 해결 방법(알고리즘)을 독립적으로 정의하고, 이를 상호 교체 가능한 형태로 캡슐화하는 디자인 패턴입니다. 이는 알고리즘의 변경과 확장을 쉽게 하며, 클라이언트 코드가 구체적인 알고리즘에 의존하지 않도록 합니다.

의존성 주입을 통한 전략 적용

다음은 .NET의 IServiceCollection 기반으로 전략 패턴을 구현한 예제입니다. 전략은 인터페이스를 통해 추상화되고, 런타임 시 필요한 구현체가 자동으로 주입됩니다.

// 서비스 컨테이너 구성
var services = new ServiceCollection();
services.AddScoped<IStorageProvider, DatabaseStorage>();
// services.AddScoped<IStorageProvider, CacheStorage>(); // 다른 전략 활성화

services.AddScoped<OrderProcessor>();

var serviceProvider = services.BuildServiceProvider();
var processor = serviceProvider.GetRequiredService<OrderProcessor>();

processor.Process(new Order { Amount = 100 });
public interface IStorageProvider
{
    void Save(object data);
}

public class DatabaseStorage : IStorageProvider
{
    public void Save(object data)
    {
        Console.WriteLine("데이터베이스에 저장됨");
    }
}

public class CacheStorage : IStorageProvider
{
    public void Save(object data)
    {
        Console.WriteLine("캐시에 저장됨");
    }
}

public class OrderProcessor
{
    private readonly IStorageProvider _storage;

    public OrderProcessor(IStorageProvider storage)
    {
        _storage = storage;
    }

    public void Process(Order order)
    {
        _storage.Save(order);
    }
}

public class Order
{
    public decimal Amount { get; set; }
}

할인 전략의 동적 선택 예제

사용자 타입에 따라 영화 티켓 가격을 다르게 계산하는 시나리오입니다. 각 전략은 고유한 할인 로직을 가집니다.

var services = new ServiceCollection();
services.AddScoped<IPriceStrategy, StudentDiscount>()
       .AddScoped<TicketCalculator>();

var provider = services.BuildServiceProvider();
var calculator = provider.GetRequiredService<TicketCalculator>();

calculator.SetBasePrice(80m);
Console.WriteLine($"기본 가격: {calculator.BasePrice}원");
Console.WriteLine($"할인 적용 후 가격: {calculator.Calculate()}원");
public interface IPriceStrategy
{
    decimal Apply(decimal basePrice);
}

public class StudentDiscount : IPriceStrategy
{
    private const decimal DISCOUNT_RATE = 0.7m;

    public decimal Apply(decimal basePrice)
    {
        Console.WriteLine("학생 할인 적용 (30% 할인)");
        return basePrice * DISCOUNT_RATE;
    }
}

public class SeniorDiscount : IPriceStrategy
{
    private const decimal DISCOUNT_RATE = 0.5m;

    public decimal Apply(decimal basePrice)
    {
        Console.WriteLine("노년 할인 적용 (50% 할인)");
        return basePrice * DISCOUNT_RATE;
    }
}

public class TicketCalculator
{
    private decimal _basePrice;
    private readonly IPriceStrategy _strategy;

    public TicketCalculator(IPriceStrategy strategy)
    {
        _strategy = strategy;
    }

    public decimal BasePrice => _basePrice;

    public void SetBasePrice(decimal price)
    {
        _basePrice = price;
    }

    public decimal Calculate()
    {
        return _strategy.Apply(_basePrice);
    }
}

이 구조는 새로운 할인 정책을 추가하거나 기존 전략을 교체하기 쉽습니다. 또한 테스트 용이성과 유지보수성이 높아지며, 전체 시스템의 확장성과 유연성을 크게 향상시킵니다.

태그: 전략패턴 의존성주입 인터페이스 알고리즘캡슐화 ASP.NET Core

6월 4일 18:23에 게시됨