C#

C# 디자인 패턴 핵심 3가지: 싱글턴·팩토리·전략 패턴 완벽 가이드

로기221 2025. 5. 20. 09:34
728x90
반응형

 

C# 디자인 패턴 기초: 싱글턴, 팩토리, 전략 패턴

웹 개발, 게임, 엔터프라이즈 시스템 등 다양한 분야에서 C#은 강력한 언어로 자리잡고 있습니다.

디자인 패턴은 코드의 재사용성, 유지보수성, 확장성을 높여주는 핵심 도구입니다.

이 글에서는 싱글턴, 팩토리, 전략 패턴을 중심으로 실제 코드 예제와 적용 사례를 설명합니다.

 

 

1. 싱글턴 패턴 (Singleton Pattern)

목적: 클래스의 인스턴스를 하나만 생성하고 전역적으로 접근 가능하게 합니다.

코드 예제

public sealed class AppConfig
{
    private static readonly Lazy<AppConfig> _instance = 
        new Lazy<AppConfig>(() => new AppConfig());
    
    public static AppConfig Instance => _instance.Value;
    
    // 설정 값 예시
    public string ApiKey { get; } = "SECRET_KEY";
    public int MaxConnections { get; } = 100;
    
    private AppConfig() { } // 외부에서 new 금지
}

// 사용 예시
var config = AppConfig.Instance;
Console.WriteLine(config.ApiKey); // "SECRET_KEY" 출력

 

실무 적용 사례

  • 설정 관리: 애플리케이션 설정(API 키, DB 연결 정보)을 싱글턴으로 중앙 관리.
  • 로깅 시스템: 모든 모듈에서 동일한 로거 인스턴스 사용.
  • 캐시 관리: 전역 캐시 저장소 구현.

주의사항

  • 스레드 안전성: Lazy<T>를 사용해 지연 생성 및 스레드 안전성 보장.
  • 과용 금지: 무분별한 사용은 코드 결합도를 높일 수 있음.

 

 

2. 팩토리 패턴 (Factory Pattern)

목적: 객체 생성 로직을 분리하여 유연성을 높입니다.

코드 예제

public interface IReport
{
    void Generate();
}

public class PdfReport : IReport
{
    public void Generate() => Console.WriteLine("PDF 리포트 생성");
}

public class ExcelReport : IReport
{
    public void Generate() => Console.WriteLine("Excel 리포트 생성");
}

public static class ReportFactory
{
    public static IReport CreateReport(string type)
    {
        return type switch
        {
            "pdf" => new PdfReport(),
            "excel" => new ExcelReport(),
            _ => throw new ArgumentException("잘못된 리포트 타입")
        };
    }
}

// 사용 예시
var report = ReportFactory.CreateReport("pdf");
report.Generate(); // "PDF 리포트 생성" 출력

 

실무 적용 사례

  • 다양한 포맷 지원: 문서 생성기(PPT, CSV, XML 등).
  • 플러그인 시스템: 확장 기능을 팩토리로 동적 로드.
  • UI 컴포넌트 생성: 플랫폼별 버튼/텍스트박스 생성.

장점

  • OCP 준수: 새로운 타입 추가 시 기존 코드 수정 없이 팩토리 확장만으로 가능.

 

3. 전략 패턴 (Strategy Pattern)

목적: 알고리즘을 런타임에 교체 가능하도록 캡슐화합니다.

코드 예제

public interface IPaymentStrategy
{
    void Pay(int amount);
}

public class CreditCardPayment : IPaymentStrategy
{
    public void Pay(int amount) => Console.WriteLine($"{amount}원 신용카드 결제");
}

public class KakaoPayPayment : IPaymentStrategy
{
    public void Pay(int amount) => Console.WriteLine($"{amount}원 카카오페이 결제");
}

public class ShoppingCart
{
    private IPaymentStrategy _paymentStrategy;
    
    public void SetPaymentStrategy(IPaymentStrategy strategy) 
        => _paymentStrategy = strategy;
    
    public void Checkout(int amount) 
        => _paymentStrategy?.Pay(amount);
}

// 사용 예시
var cart = new ShoppingCart();
cart.SetPaymentStrategy(new CreditCardPayment());
cart.Checkout(50000); // "50000원 신용카드 결제" 출력

 

실무 적용 사례

  • 결제 시스템: 신용카드, 페이팔, 암호화폐 등 결제 방식 전환.
  • 정렬 알고리즘: 데이터에 따라 퀵정렬/병합정렬 동적 선택.
  • AI 행동 패턴: 게임 캐릭터의 공격/방어 전략 변경.

장점

  • OCP & SRP 준수: 알고리즘 변경이 다른 코드에 영향 없음.

 

패턴 선택 가이드

상황적합한 패턴
전역적으로 단일 인스턴스 필요 싱글턴
객체 생성 로직이 복잡할 때 팩토리
알고리즘을 유연하게 교체 필요 전략

 

 

 

결론

  • 싱글턴: 설정, 로깅 등 전역 상태 관리에 최적화.
  • 팩토리: 객체 생성의 유연성 확장성이 필요할 때.
  • 전략: 알고리즘의 런타임 교체가 필요할 때.

디자인 패턴은 문제 해결을 위한 도구일 뿐, 모든 상황에 적용해야 하는 것은 아닙니다. 실제 프로젝트에서는 코드 복잡도와 유지보수 비용을 고려해 적절히 선택해야 합니다.

728x90
반응형