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 디자인 패턴 서적을 참고해 보세요! 😊