# 데코레이터 패턴
## 정의
데코레이터 패턴은 기존 코드를 수정하지 않고도 기능을 동적으로 추가하거나 변경할 수 있게 해주는 디자인 패턴이다. 이 패턴은 구조 패턴의 한 종류로, 기본적인 객체에 추가적인 기능을 부여하기 위해 '감싸는' 형태로 적용된다.
이를 통해 기존 클래스를 수정하지 않고도 새로운 기능을 추가할 수 있다.
### 장점
기존 코드를 수정하지 않고도 기능을 추가하거나 변경할 수 있다.
단일 책임 원칙을 준수한다.
각 데코레이터는 자신의 기능만을 추가하므로 기능이 분리되어 코드의 유지보수가 쉽다.
## 예제 시나리오
어느 한 사람이 카페에 가서 아이스티의 샷 추가를 하는 상황이다.
### 구현 순서
1. 음료를 나타내는 Beverage 인터페이스 생성 (음료 설명, 가격 반환 메서드 포함)
2. Beverage를 상속받는 IceTea 클래스 생성
3. 데코레이터 역할을 하는 abstract class BeverageDecorator 생성
4. BeverageDecorator를 상속받는 Shot 클래스 생성
5. 메인 메서드에서 IceTea 객체를 생성하고 가격과 설명 출력 후 Shot을 추가한 후 가격과 설명 출력
1. 음료를 나타내는 Beverage 인터페이스 생성 (음료 설명, 가격 반환 메서드 포함)
// Beverage interface 생성
interface Beverage {
fun getDescription(): String
fun cost(): Int
}
2. Beverage를 상속 받는 IceTea 클래스 생성
// Beverage interface 생성
interface Beverage {
fun getDescription(): String
fun cost(): Int
}
3. 데코레이터 역할을 하는 abstract class BeverageDecorator 생성
// 데코레이터 생성
abstract class BeverageDecorator(private val beverage: Beverage) : Beverage {
override fun getDescription() = beverage.getDescription()
override fun cost() = beverage.cost()
}
4. BeverageDecorator를 상속받는 Shot 클래스 생성
// 데코레이터를 상속받아 구체적인 기능을 추가하는 Shot 클래스 생성
class Shot(beverage: Beverage) : CondimentDecorator(beverage) {
override fun getDescription() = super.getDescription() + ", 샷 추가"
}
5. 메인 메서드에서 IceTea 객체를 생성하고 가격과 설명 출력 후 Shot을 추가한 후 가격과 설명 출력
fun main() {
// Beverage 객체인 IceTea 생성
var beverage: Beverage = IceTea()
// 현재 beverage의 설명과 가격 출력
println("${beverage.getDescription()} ${beverage.cost()}")
// 만들어진 beverage객체에 Shot객체로 감싼다
beverage = Shot(beverage)
// 감싸진 객체의 설명과 가격 출력
println("${beverage.getDescription()} ${beverage.cost()}")
}
출력 결과