Decorator Pattern
View all Design Patterns
객체에 동적으로 책임을 추가해 객체를 동적으로 확장할 수 있는 방법이다. 기본적으로 상속 관계는 정적이며, 자식 클래스는 하나의 부모 클래스만 가질 수 있다. Decorator Pattern은 상속 관계가 아닌 집합 또는 합성 관계로 이를 해결한다.
Class Diagram
Abstract overview
Concrete example
Code
interface Request {
message: string;
}
interface Response {
message: string;
}
interface RequestHandler {
handleRequest(request: Request): Response;
}
class ConcreteHandler implements RequestHandler {
handleRequest(request: Request): Response {
return { success: true };
}
}
abstract class MiddlewareDecorator {
protected handler: RequestHandler;
constructor(handler: RequestHandler) {
this.handler = handler;
}
abstract handleRequest(request: Request): Response;
}
class LoggingMiddleware extends MiddlewareDecorator {
handleRequest(request: Request): Response {
console.log("Logging request...");
return this.handler.handleRequest(request);
}
}
class AuthenticationMiddleware extends MiddlewareDecorator {
handleRequest(request: Request): Response {
console.log("Authentication request...");
return this.handler.handleRequest(request);
}
}
const handler = new ConcreteHandler();
const logger = new LoggingMiddleware(handler);
const authenticator = new AuthenticationMiddleware(logger);
const response = authenticator.handleRequest({
message: "This is request message",
});
console.log(response);
//Authentication request...
// Logging request...
// { success: true }
ConcreteHandler
→ LoggingMiddleware
→ AuthenticationMiddleware
위와 같이 서버의 미들웨어를 순서대로 추가하는 예시를 들 수 있다.
Pros and Cons
Pros
- 기존 코드의 변경 없이 런타임 시 객체에 새로운 책임을 추가할 수 있다.
- 재사용성이 향상된다.
- 각 데코레이터는 하나의 책임을 관리하기 때문에 SRP(Single Responsibility Principle)를 준수한다.
Cons
- 기본적으로 객체에 책임을 순차적으로 적용하기 때문에, 그 순서에 영향을 받는다.