데코레이터는 객체들을 새로운 행동들을 포함한 특수 래퍼 객체들 내에 넣어서 행동들을 해당 객체들에 연결시키는 구조적 디자인 패턴이다.
객체의 동작을 변경을 위해 상속을 사용하는 경우 주의 사항
- 상속은 정적이다. 런타임(실행시간) 때 기존 객체의 행동을 변경할 수 없다. 전체 객체를 다른 자식 클래스에서 생성된 다른 객체로만 바꿀 수 있다.
- 자식 클래스는 하나의 부모 클래스만 가질 수 있다. 대부분 언어에서의 상속은 클래스가 동시에 여러 클래스의 행동을 상속하도록 허용하지 않는다.
객체의 동작을 변경을 위해 상속 대신 집합 관계 또는 합성을 사용하는 경우
집합 관계에서는 한 객체가 다른 객체에 대한 참조를 갖고 일부 작업을 위임한다. 반면, 상속을 사용하면 객체 자체가 부모 클래스에서 행동을 상속한 후 해당 작업을 수행할 수 있다.
'도우미' 객체를 다른 객체로 쉽게 대체하여 런타임 때 컨테이너의 행동을 변경할 수 있다. 객체는 여러 클래스의 행동들을 사용할 수 있고, 여러 객체에 대한 참조들이 있으며 이 객체들에 모든 종류의 작업을 위임한다. 집합 관계/합성은 데코레이터를 포함한 많은 디자인 패턴의 핵심 원칙이다.
'래퍼'는 패턴의 주요 아이디어를 명확하게 표현하는 데코레이터 패턴의 별명이다. 래퍼는 일부 대상 객체와 연결할 수 있는 객체다. 래퍼에는 대상 객체와 같은 메서드들의 집합이 포함되어 있으며, 래퍼는 자신이 받는 모든 요청을 대상 객체에 위임한다. 그러나 래퍼는 이 요청을 대상에 전달하기 전이나 후에 무언가를 수행하여 결과를 변경할 수 있다.
사용 예시
// ContentCachingRequestWrapper
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
public ContentCachingRequestWrapper(HttpServletRequest request, int cacheLimit) {
super(request);
int contentLength = request.getContentLength();
this.cachedContent = (contentLength > 0 ?
new FastByteArrayOutputStream((cacheLimit > 0 ? Math.min(contentLength, cacheLimit) : contentLength)) :
new FastByteArrayOutputStream());
this.contentCacheLimit = (cacheLimit > 0 ? cacheLimit : null);
}
}
// HttpServletRequestWrapper
public class HttpServletRequestWrapper extends ServletRequestWrapper implements HttpServletRequest
ContentCachingRequestWrapper
에서 '도우미' 객체는 HttpServletRequest
에 해당하고 '래퍼' 객체는 ContentCachingRequestWrapper
에 해당한다.
// ContentCachingRequestWrapper
@Override
public ServletInputStream getInputStream() throws IOException {
if (this.inputStream == null) {
this.inputStream = new ContentCachingInputStream(getRequest().getInputStream());
}
return this.inputStream;
}
// ServletRequestWrapper
@Override
public ServletInputStream getInputStream() throws IOException {
return this.request.getInputStream();
}
ServletRequestWrapper
의 메서드 중 하나인 getInputStream
의 구현을 살펴보면 ContentCachingRequestWrapper
라는 네이밍처럼 inputStream
에 해당하는 값을 캐싱하는 로직이 추가되어 있음을 확인할 수 있다.
'자바' 카테고리의 다른 글
Facade Pattern 정리 (0) | 2025.04.17 |
---|---|
Delegation Pattern 정리 (0) | 2025.04.14 |
Adapter Pattern 정리 (0) | 2025.04.08 |
Class.isAssignableFrom(Class<?> var1) 정리 (0) | 2025.04.07 |
코틀린 receiver 이해를 위한 예시 정리 (0) | 2025.04.03 |