디자인 패턴(구조 패턴) 실제로 어떻게 적용할까 ? (4편)

소일로·2025년 2월 3일
0
post-thumbnail

디자인 패턴: 컴포짓 패턴과 데코레이터 패턴

이번 글에서는 컴포짓 패턴(Composite Pattern)과 데코레이터 패턴(Decorator Pattern)에 대해 알아보고, 각각의 실제 활용 사례, 장단점, 그리고 유의점을 살펴보겠습니다.


1. 컴포짓 패턴 (Composite Pattern)

언제 사용할까?

  • 개별 객체와 객체 그룹을 동일한 방식으로 처리해야 할 때.
  • 트리 구조와 같은 계층 구조를 표현할 때.

실제 적용

  • 파일 시스템: 폴더 안에 파일과 다른 폴더를 포함하는 구조.
  • UI 프레임워크: 버튼, 텍스트박스 같은 개별 요소와 패널 같은 컨테이너를 동일한 방식으로 처리.

코드 예제 (Java)

// 컴포넌트 인터페이스
interface Graphic {
    void draw();
}

// 리프(Leaf) 클래스
class Circle implements Graphic {
    @Override
    public void draw() {
        System.out.println("Drawing a Circle");
    }
}

// 컴포짓(Composite) 클래스
class GraphicGroup implements Graphic {
    private List<Graphic> graphics = new ArrayList<>();

    public void add(Graphic graphic) {
        graphics.add(graphic);
    }

    @Override
    public void draw() {
        for (Graphic graphic : graphics) {
            graphic.draw();
        }
    }
}

// 사용
Graphic circle1 = new Circle();
Graphic circle2 = new Circle();
GraphicGroup group = new GraphicGroup();
group.add(circle1);
group.add(circle2);
group.draw();

장점

  • 개별 객체와 객체 그룹을 동일하게 처리 가능.
  • 트리 구조 표현에 적합하며, 관리가 용이함.

유의점

  • 너무 복잡한 트리 구조는 관리와 디버깅이 어려울 수 있음.
  • 단순한 구조에 적용하면 불필요한 복잡성을 초래할 수 있음.

2. 데코레이터 패턴 (Decorator Pattern)

언제 사용할까?

  • 객체의 기능을 동적으로 추가하거나 확장해야 할 때.
  • 상속 없이 기능을 조합하거나 확장할 필요가 있을 때.

실제 적용

  • Java I/O: InputStream, OutputStream의 기능 확장.
  • NestJS: 메서드에 추가 기능을 적용하는 데코레이터(@Injectable, @Controller 등).

코드 예제 (Java)

// 컴포넌트 인터페이스
interface Notifier {
    void send(String message);
}

// 구체적인 컴포넌트
class BasicNotifier implements Notifier {
    @Override
    public void send(String message) {
        System.out.println("Sending message: " + message);
    }
}

// 데코레이터 추상 클래스
abstract class NotifierDecorator implements Notifier {
    protected Notifier notifier;

    public NotifierDecorator(Notifier notifier) {
        this.notifier = notifier;
    }

    public void send(String message) {
        notifier.send(message);
    }
}

// 구체적인 데코레이터
class EmailNotifier extends NotifierDecorator {
    public EmailNotifier(Notifier notifier) {
        super(notifier);
    }

    @Override
    public void send(String message) {
        super.send(message);
        System.out.println("Sending email notification: " + message);
    }
}

class SMSNotifier extends NotifierDecorator {
    public SMSNotifier(Notifier notifier) {
        super(notifier);
    }

    @Override
    public void send(String message) {
        super.send(message);
        System.out.println("Sending SMS notification: " + message);
    }
}

// 사용
Notifier notifier = new BasicNotifier();
Notifier emailNotifier = new EmailNotifier(notifier);
Notifier smsNotifier = new SMSNotifier(emailNotifier);

smsNotifier.send("Hello, Decorator Pattern!");

장점

  • 상속 없이 기능을 유연하게 확장 가능.
  • 객체의 기능을 동적으로 추가할 수 있어 조합이 용이함.

유의점

  • 데코레이터가 많아지면 코드 구조가 복잡해질 수 있음.
  • 디버깅 시 어떤 데코레이터가 적용되었는지 파악이 어려울 수 있음.

결론

  • 컴포짓 패턴은 트리 구조의 데이터나 계층적인 관계를 관리할 때 유용합니다.
  • 데코레이터 패턴은 객체의 기능을 동적으로 확장하거나 조합할 때 적합합니다.
profile
백엔드 개발자

0개의 댓글