일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- jwt
- 빈 충돌
- 전략패턴 #StrategyPattern #디자인패턴
- spring batch 5.0
- 개발자 취업
- 프로그래머스
- jwttoken
- 파이썬
- 구글 OAuth login
- 1주일회고
- 항해99
- @FeignClient
- 디자인 패턴
- infcon 2024
- 단기개발자코스
- JavaScript
- 프로그래머스 이중우선순위큐
- 인프콘 2024
- 개발자부트캠프추천
- 빈 조회 2개 이상
- 커스텀 헤더
- DesignPattern
- TiL
- KPT회고
- 99클럽
- 취업리부트코스
- 디자인패턴
- Python
- 코딩테스트 준비
- Spring multimodule
- Today
- Total
m1ndy5's coding blog
데코레이터 패턴(Decorator Pattern) 본문
데코레이터 패턴 정의
주어진 상황 및 용도에 따라 어떤 객체에 책임을 덧붙이는 패턴으로, 기능 확장이 필요할 때 서브클래싱 대신 쓸 수 있는 유연한 대안이 될 수 있는 패턴
객체에 요소들을 추가할 때 원본 코드를 수정하지 않고 동적으로 더할 수 있는 패턴이다.
OCP(Open-Closed Principle)
확장에는 열려 있지만 변경에는 닫혀있어야 한다는 원칙으로 데코레이터 패턴은 이 원칙을 따른다.(기존 코드를 건드리지 않고 확장을 할 수 있기 때문)
예시 상황
예를 들어서 엽기떡볶이를 시켜먹는다고 상상을 해보자.
떡볶이는 착한맛, 순한맛, 덜매운맛, 오리지널맛, 더매운맛 중에 하나를 선택해야하고 토핑으로는 계란추가, 떡사리 추가, 베이컨 추가, 우동면 추가 등등 여러가지를 추가할 수있고 물론 똑같은 토핑을 여러번 추가할 수도 있다.
이 때 나올 수 있는 가지수는 굉장히 많다.
계란, 중국당면을 추가한 오리지널 엽떡도 있을 수 있고 우동면만 2번 추가한 순한맛 엽떡 등등 경우의 수는 굉장히 많을 것이다.
만약 떡볶이라는 인터페이스를 하나 만들고 이 떡볶이 인터페이스를 구현한 각기다른 떡볶이들 클래스들을 만든다면 아예 관리를 못할 것이다.
public interface 떡볶이{
public String description();
public int cost();
}
public class 계란중국당면오리지널엽떡 implements 떡볶이{
@Override
public String description(){
return "계란, 중국당면을 추가한 오리지널 엽떡입니다";
}
@Override
public int cost(){
return 15000;
}
}
.
.
.
데코레이터 패턴 적용하기
우선 본체가 되는 떡볶이 인터페이스를 만든다.(추상클래스여도 되고 용도에 맞게 만들면 됨)
public interface 떡볶이{
public String description();
public int cost();
}
아까 떡볶이의 맛이 여러가지 있었기 때문에 떡볶이 인터페이스를 구현한 클래스를 만든다.
public class 덜매운맛떡볶이 implements 떡볶이{
@Override
public String description(){
return "덜매운맛 엽떡";
}
@Override
public int cost(){
return 14000;
}
}
public class 오리지널떡볶이 implements 떡볶이{
@Override
public String description(){
return "오리지널 엽떡";
}
@Override
public int cost(){
return 14000;
}
}
이제 토핑 추상 클래스를 만들어준다.(데코레이터)
public abstract class Topping implements 떡볶이{
떡볶이 ddeok;
public abstract String description();
public abstract int cost();
}
이 때 여기서 가장 중요한점!!
반드시 데코레이터가 객체 자신이 감싸고 있는 객체랑 같은 인터페이스를 implements하고 구성으로도 넣어줘야한다.
이유는 구성으로 받아온 떡볶이를 자신이 토핑을 추가한 떡볶이로 감쌀 수 있어야 하기 때문이다.
ex) 오리지널맛 떡볶이 + 치킨토핑떡볶이 = 치킨토핑 오리지널맛 떡볶이
치킨토핑 오리지널맛 떡볶이 + 중국당면떡볶이 = 치킨토핑 중국당면 오리지널맛 떡볶이
이제 토핑 추상클래스를 상속받은 갖가지 토핑클래스를 만들어보자
public class 중국당면 extends Topping{
// 어떤 떡볶이를 꾸밀건지
public 중국당면(떡볶이 dd){
this.ddeok = dd;
}
public String description(){
return "중국당면" + ddeok.description();
}
public int cost(){
return ddeok.cost() + 2500;
}
}
public class 우동면 extends Topping{
public 우동면(떡볶이 dd){
this.ddeok = dd;
}
public String description(){
return "우동면" + ddeok.description();
}
public int cost(){
return ddeok.cost() + 1500;
}
}
이제 어떻게 사용하는지 한번 예시를 보자!
public class Main{
public static void main(String args[]){
떡볶이 ddeokbokki = new 덜매운맛떡볶이();
// 덜매운맛 엽떡 14000원
System.out.println(ddeokbokki.description() + " " + ddeokbokki.cost() + "원");
ddeokbokki = new 중국당면(ddeokbokki);
// 중국당면 덜매운맛 엽떡 16500원
System.out.println(ddeokbokki.description() + " " + ddeokbokki.cost() + "원");
ddeokbokki = new 우동면(ddeokbokki);
// 우동면 중국당면 덜매운맛 엽떡 18000원
System.out.println(ddeokbokki.description() + " " + ddeokbokki.cost() + "원");
}
}
데코레이터 패턴을 사용하면 새로운 행위가 추가될 때마다 데코레이터 객체를 만들어 사용하면 원본 코드를 변경할 필요가 없어 좋지만
자칫 잘못하면 자잘한 객체가 너무 많이 추가될 수 있어 필요 이상으로 사용할 경우 코드가 굉장히 복잡해질 수 있다는 단점이 있다.
'백엔드 with java > Design Pattern' 카테고리의 다른 글
싱글톤(Singleton) feat. 스프링 (0) | 2023.12.04 |
---|---|
추상 팩토리 패턴(Abstract Factory Pattern) (0) | 2023.11.26 |
팩토리 메소드 패턴(Factory Method Pattern) (0) | 2023.11.26 |
옵저버 패턴(Observer Pattern) (1) | 2023.11.22 |
전략 패턴(Strategy Pattern) (0) | 2023.11.21 |