새로운 서비스의 추가가 필요할때 일반적으로 상속을 이용합니다.
1. 나중 추가사항이 생긴다면 superclass를 수정하고 기능을 집어넣어야 합니다.
2. 1번으로 인하여 superclass는 비대해지고
SOLID의 SRP를 위반합니다. (어떤 특정 subClass A에서만 사용하는 메소드가 B, C에도 상속됩니다.)
그래서 OCP의 컨셉을 활용하여 해결하려고 시도하는 디자인 패턴입니다.
class Food {
add() {
//재료 추가
}
}
class Ramen extends Food {
addKelp() {}
addNoodle() {}
add() {
this.addNoodle();
this.addKelp();
}
}
그런데 라면의 인기가 높아져서 라면에 온갖 고추장, 치즈, 짜장, 곰탕등 소스를 집어넣기 시작했습니다.
입니다.
그래서 데코레이터를 사용해서 치즈짜장라면과 치즈곰탕라면을..
상속을 사용하지 않고 데코레이터를 사용해서 구현해봅시다...
(글 쓰면서 뭔가 내용이 산으로 가는 느낌인데..?)
class Food {
add() {
//재료 추가
}
}
class Ramen extends Food {
addKelp() {
return 'add Kelp ';
}
addNoodle() {
return 'add noodle ';
}
assemble() {
return this.addNoodle() + this.addKelp();
}
}
class RamenDecorator extends Food {
constructor(Ramen) {
super();
this.Ramen = Ramen;
}
assemble() {
return this.Ramen.assemble();
}
}
우선 Base가 되는 Ramen과 Ramen Decorator입니다.
RamenDecorator는 만들고 싶은 Ramen을 주입받아 조립해 사용합니다.
치즈라면을 일단 만들어 봅시다.
class CheeseRamenDecorator extends RamenDecorator {
addCheese() {
return 'add cheese';
}
assemble() {
return super.assemble() + this.addCheese();
}
}
const CheeseRamen = new CheeseRamenDecorator(new Ramen());
console.log(CheeseRamen.assemble());
그림으로 보면 이런 상태입니다.
$ node test.js
add noodle add Kelp add cheese
코드를 실제로 돌려보면 잘 적용된걸 확인할 수 있습니다.
class BlackbeanSauceRamenDecorator extends RamenDecorator {
addBlackbeanSauce() {
return 'add BlackbeanSauce';
}
assemble() {
return super.assemble() + this.addBlackbeanSauce();
}
}
class BeefBoneSoupRamenDecorator extends RamenDecorator {
addBeefBoneSoup() {
return 'add BeefBoneSoup';
}
assemble() {
return super.assemble() + this.addBeefBoneSoup();
}
}
const CheeseRamen = new CheeseRamenDecorator(new Ramen());
console.log(CheeseRamen.assemble());
const CheeseBlackbeanSauceRamen = new BlackbeanSauceRamenDecorator(
new CheeseRamenDecorator(new Ramen()),
);
const CheeseBeefBoneSoupRamen = new BeefBoneSoupRamenDecorator(
new CheeseRamenDecorator(new Ramen()),
);
console.log(CheeseBlackbeanSauceRamen.assemble());
console.log(CheeseBeefBoneSoupRamen.assemble());
아.. 라면 이름 예시를 잘못들었는데 지금 돌이킬순 없는거 같아요..
그림으로 보면 이런상태입니다.
add noodle add Kelp add cheeseadd BlackbeanSauce
add noodle add Kelp add cheeseadd BeefBoneSoup
코드를 실제로 돌려보면 잘 적용된걸 확인할 수 있습니다.
그리고 상속으로 구현했을때보다 훨씬 깨끗해진걸 볼 수 있습니다.
지금은 조합 예시가 2~3개이지만 프로그램이 발전되며 조합이 수십~수백가지로 늘어났을때에도 상속보다 유연하게 처리 가능해진걸 확인할 수 있었습니다.
tmi 하나 하자면.. K사 기술면접에서 super class에 공통 함수를 놔둔다면 안쓰이는 subclass에서는 이것을 어떻게 처리해야할것인가라는 질문이 나왔었는데 그 당시에는 답변을 못했다가 오늘 알게됬네요 ㅠㅠ
https://gmlwjd9405.github.io/2018/07/09/decorator-pattern.html
https://steady-coding.tistory.com/391
'소프트웨어공학 > 디자인패턴' 카테고리의 다른 글
프론트엔드에서의 레포지토리 패턴? (0) | 2022.03.18 |
---|---|
[행위] 책임 연쇄 패턴 (0) | 2022.03.13 |
[행위] 전략 패턴 & 커맨드 패턴 (0) | 2022.03.07 |
[행동] 중재자 패턴 (1) | 2022.03.01 |
디자인 패턴의 종류 (0) | 2022.02.24 |