데코레이터는 기존 객체의 동작을 동적으로 증강시키는 패턴입니다.
상속과의 차이점은 동일한 클래스의 모든 객체에 적용되지 않고 명시적으로 데코레이트한 인스턴스에만 추가되는 것 입니다.
데코레이트 라는 이름처럼 기존 객체를 추가적으로 좀 더 꾸며준다고 보면 쉬울 것 같습니다.
방식은 프록시 패턴과 비슷하게 볼 수 있지만, 객체의 기존 동작을 수정하는 대신 새로운 기능을 추가함으로써 기능을 증가시킵니다.
const decorate = (target) => {
target.method2 = () => {
return 'method2';
};
return target;
};
class Subject {
method1() {
return 'method1';
}
}
const decoratedSubject = decorate(new Subject());
console.info(decoratedSubject.method1()); // "method1"
console.info(decoratedSubject.method2()); // "method2"
JS 에서 구현은 간단합니다. 프록시 패턴과 굳이 구분해야 할까 싶을정도로 비슷해 보이기도 하구요.
객체 지향의 코드에선, 이런식으로 구현하기 보단 적당한 상속과 객체 간의 합성을 통해 데코레이터 패턴을 구현합니다.
interface Character {
attack(): void;
}
class Warrior implements Character {
attack(): void {
console.info('attack with sword');
}
}
class Wizard implements Character {
attack(): void {
console.info('attack with magic');
}
}
abstract class MergedCharacter implements Character {
protected readonly character: Character;
constructor(character: Character) {
this.character = character;
}
attack(): void {
this.character.attack();
}
}
class AdvancedCharacter extends MergedCharacter {
constructor(character: Character) {
super(character);
}
attack(): void {
super.attack();
this.advancedAttack();
}
private advancedAttack(): void {
console.info('advanced attack');
}
}
const c1 = new Warrior();
c1.attack(); // attack with sword
const c2 = new Wizard();
c2.attack(); // attack with magic
const advancedC1 = new AdvancedCharacter(new Warrior());
advancedC1.attack(); // attack with sword advanced attack
뭔가 적당한 예시가 아닐 수도 있긴 합니다만..
전사, 마법사 라는 클래스가 있는 상태에서 각각 승급한 형태를 구현하려 할 때의 상황입니다.
Warrior, Wizard 를 상속하는 또다른 클래스를 만들 수도 있겠지만 승급에 의해 향상된 공격만 추가되는 정도의 요구사항이라면
AdvancedCahracter 를 만들어 기존 Character 와 합성하는 형태로도 작성이 가능하다는 것입니다.
물론 실제 게임이었다면 전사, 마법사라는 직업이 승급한 형태가 동일한 기능을 제공하진 않을테니 이런식의 구현이 쓰일 일이
오히려 없겠지만, 예시로 봐주시면 좋을 것 같습니다.
어느정도 예시를 통해 데코레이터 패턴의 장단점을 알 수 있게 되었습니다.
장점
- 유연성
- 기능 확장 시 상속 없이 가능
- 런타임에서의 동적 기능 추가
단점
- 코드가 복잡해질 수 있음
- 객체가 오히려 더 늘어날 수 있음
- 런타임에 추가된다는 건 디버깅의 난이도를 올릴 수 있음
- 기존 데코레이터 패턴이 추구하려는 방향과 멀어질 수 있다..
단점에서 보이듯이 데코레이터 패턴을 적용하기 전 더 괜찮은 설계 방법은 없을지 고민하는게 좋을 것 같습니다.
'Backend > 디자인 패턴' 카테고리의 다른 글
Strategy Pattern (전략 패턴) (0) | 2022.10.24 |
---|---|
Adapter Pattern (어댑터 패턴) (0) | 2022.10.08 |
Proxy Pattern (프록시 패턴) (0) | 2022.09.25 |
Revealing Constructor Pattern (공개 생성자 패턴) (0) | 2022.09.18 |
Factory Pattern (팩토리 패턴) (0) | 2022.09.11 |