본문 바로가기

카테고리 없음

디자인 패턴 - 행동 in C#

C#에서 디자인 패턴은 코드의 유지보수성과 확장성을 높이는 데 중요한 역할을 합니다. 그중 **행동 패턴(Behavioral Patterns)**은 객체 간의 책임 분배와 상호작용을 효율적으로 설계하는 데 집중합니다.

행동 패턴은 다음과 같은 상황에서 유용합니다:

  • 객체 간의 통신을 구조화하고 싶을 때
  • 특정 동작을 변경하거나 확장할 때
  • 객체의 결합도를 낮춰 유지보수성을 높이고 싶을 때

전략 패턴 (Strategy Pattern)

 

전략 패턴은 런타임에 알고리즘을 변경할 수 있도록 하는 패턴입니다.

사용 사례

  • 여러 개의 정렬 알고리즘을 유연하게 교체할 때
  • 결제 방식(카드, 계좌이체, 페이팔 등)을 런타임에 변경할 때
// 전략 인터페이스 정의
public interface IStrategy {
    void Execute();
}

// 전략 클래스 구현
public class ConcreteStrategyA : IStrategy {
    public void Execute() {
        Console.WriteLine("전략 A 실행");
    }
}

public class ConcreteStrategyB : IStrategy {
    public void Execute() {
        Console.WriteLine("전략 B 실행");
    }
}

// 컨텍스트 클래스
public class Context {
    private IStrategy _strategy;
    public void SetStrategy(IStrategy strategy) {
        _strategy = strategy;
    }
    public void ExecuteStrategy() {
        _strategy.Execute();
    }
}

// 실행 코드
class Program {
    static void Main() {
        Context context = new Context();
        context.SetStrategy(new ConcreteStrategyA());
        context.ExecuteStrategy();
        
        context.SetStrategy(new ConcreteStrategyB());
        context.ExecuteStrategy();
    }
}

옵저버 패턴 (Observer Pattern)

옵저버 패턴은 객체 간 1:N 의존성을 정의하여 한 객체의 상태 변화가 다른 객체에 자동으로 반영되도록 합니다.

사용 사례

  • GUI 이벤트 리스너
  • 주식 가격 알림 시스템
public interface IObserver {
    void Update(string message);
}

public class ConcreteObserver : IObserver {
    private string _name;
    public ConcreteObserver(string name) { _name = name; }
    public void Update(string message) {
        Console.WriteLine($"{_name} received: {message}");
    }
}

public class Subject {
    private List<IObserver> _observers = new List<IObserver>();
    public void Attach(IObserver observer) {
        _observers.Add(observer);
    }
    public void Notify(string message) {
        foreach (var observer in _observers) {
            observer.Update(message);
        }
    }
}

class Program {
    static void Main() {
        Subject subject = new Subject();
        IObserver observer1 = new ConcreteObserver("Observer 1");
        IObserver observer2 = new ConcreteObserver("Observer 2");

        subject.Attach(observer1);
        subject.Attach(observer2);

        subject.Notify("데이터 변경됨");
    }
}

책임 연쇄 패턴 (Chain of Responsibility Pattern)

책임 연쇄 패턴은 요청을 처리할 수 있는 객체들이 체인 형태로 연결되어 있고, 요청이 해당 객체들을 따라 이동하며 처리되는 패턴입니다.

사용 사례

  • 로그 필터링 시스템 (DEBUG, INFO, ERROR)
  • 요청을 단계적으로 처리하는 시스템
public abstract class Handler {
    protected Handler next;
    public void SetNext(Handler nextHandler) {
        next = nextHandler;
    }
    public abstract void HandleRequest(int level);
}

public class ConcreteHandlerA : Handler {
    public override void HandleRequest(int level) {
        if (level <= 1) {
            Console.WriteLine("Handler A가 처리했습니다.");
        } else if (next != null) {
            next.HandleRequest(level);
        }
    }
}

public class ConcreteHandlerB : Handler {
    public override void HandleRequest(int level) {
        if (level <= 2) {
            Console.WriteLine("Handler B가 처리했습니다.");
        } else if (next != null) {
            next.HandleRequest(level);
        }
    }
}

class Program {
    static void Main() {
        Handler handlerA = new ConcreteHandlerA();
        Handler handlerB = new ConcreteHandlerB();
        handlerA.SetNext(handlerB);

        handlerA.HandleRequest(2);
    }
}

결론

C#의 행동 패턴은 객체 간 관계를 효율적으로 관리하고 유연한 시스템을 구축하는 데 매우 유용합니다. 위에서 소개한 전략 패턴, 옵저버 패턴, 책임 연쇄 패턴 외에도 커맨드 패턴, 상태 패턴, 템플릿 메서드 패턴 등이 있으며, 프로젝트의 요구 사항에 맞춰 적절히 활용하면 더욱 강력한 소프트웨어를 개발할 수 있습니다.

행동 패턴 종류 및 사용 용도

패턴 사용 용도

패턴 사용 용도
전략 패턴 알고리즘을 유연하게 변경할 때
옵저버 패턴 객체 상태 변화를 구독자에게 자동으로 반영할 때
책임 연쇄 패턴 요청을 여러 단계로 처리할 때
커맨드 패턴 요청을 객체로 캡슐화하고 실행을 지연하거나 취소할 때
상태 패턴 객체의 상태에 따라 동작을 변경할 때
템플릿 메서드 패턴 알고리즘의 구조를 정의하고 일부 단계를 서브클래스에서 구현할 때

💡 더 많은 디자인 패턴을 학습하고 싶다면? C# 디자인 패턴에 대한 심화 학습을 원하시면, GoF 디자인 패턴 서적을 참고해 보세요! 😊