Decorator 패턴

뾰족머리삼돌이·2024년 10월 2일
0

디자인패턴

목록 보기
16/21

기존 클래스의 기능을 확장하기 위해 사용되는 보편적인 방식은 상속에 의한 확장이다.
공통되는 작업을 하는 부분을 인터페이스나 상위 클래스로 추출해내고, 세부작업은 하위 클래스에 작성하는 방식이다.

상속에 의한 확장은 손쉽게 구현할 수 있지만, 기능의 수 만큼 하위클래스가 늘어나는 문제가 있다.

예를들어, A와 B라는 하위클래스가 있다면 이를 복합적으로 수행하기 위해서는 A+B 라는 하위클래스를 또 구성해야한다.
심지어 Java와 같은 언어는 다중상속을 지원하지 않기때문에 하위클래스를 구성하는 과정에서 각 클래스의 내용을 중복으로 작성해야한다.

애플리케이션에는 A와 B의 상위클래스 타입의 필드 하나만 있다고 가정했다

즉, 상속에 의한 관계는 하위클래스의 기능을 둘 이상 표현하기 위해서는 새로운 하위클래스를 생성해내야 한다.

이러한 문제에 대한 해결책으로 제시된 것이 집합에 의한 관계다.
풀어서 설명하자면 클래스내에서 다른 객체에 대한 참조를 가지고 일부 작업을 위임하는 것이다.

앞선 예시를 적용시켜보자면 클라이언트 -> A -> B 의 순으로 호출을 시킨다는 말이다.
코드로 살펴보자면 아래 형태가 될 것이다.

stack = new Sample();
stack = new ADecorator(stack);
stack = new BDecorator(stack);

이런 식으로 데코레이터의 생성자를 이용하여 현재 클래스의 객체를 참조값으로 전달하는 것이다.

이렇게되면 최종적으로 작업을 수행할 때, BDecorator -> ADecorator -> Sample 순으로 작업수행이 전달된다.
따라서 수행되는 작업의 순서는 Sample -> A -> B가 된다.

동작방식에서 볼 수 있듯이 Wrapper 클래스가 데코레이터 패턴에 해당된다.
실제 대상과 연결되기 전에 작업을 수행하는 중간 클래스라는 점에서는 프록시와 유사하기도 하다.

프록시는 객체 접근에 중점을 둔다면 데코레이터는 기능 확장에 중점을 두고 있다

실제 구조를 살펴보면 기초가 되는 BaseDecorator를 기준으로 각 컴포넌트에 필요한 하위 데코레이터들이 존재한다.
컴포넌트는 BaseDecorator의 필드타입이면서 공통 인터페이스Component를 두고 있으며, 생성자를 통해 이를 주입받는다.

이렇게 되면 Decorator의 생성자로 Component의 하위 클래스들을 주입받을 수 있게 되며,
excute() 호출을 통해 데코레이터 자신의 필드인 wrappeeexcute()를 실행시킨다.

a = new ConcComponent()
b = new ConcDecorator1(a)
c = new ConcDecorator2(b)
c.excute()

위 코드의 최종적인 호출 순서는 Decorator -> Decorator -> Component 의 순이 된다.
세부 코드실행은 역순으로 Component -> Decorator -> Decorator가 될 것이다.

0개의 댓글

관련 채용 정보