- 객체를 동적으로 확장할 필요가 있을 때
- 객체에 첨가할 데이터가 다양하고 일정하지 않을 때 효율적
- 대신 자잘한 객체가 많아지고 코드가 필요 이상으로 복잡해 질 수도 있다.
- 한 객체를 감싸기 위해 한 개 혹은 여러 개의 Decorator 를 사용할 수 있다.
- Decorator 는 Decorate 하는 객체와 같은 type 을 가진다
- Decorator 는 행위(behavior)를 객체에 위임할 수도 있고 객체로부터 위임 받을 수도 있다
- 객체는 언제든지 Decorate 될 수 있어서, 런타임에 동적으로 얼마든지 많은 Decorator 로 객체를 감쌀 수 있다.
class Topping { // abstract class
class func getCost() -> Int {
return 0
}
}
class Nuts: Topping {
override class func getCost() -> Int {
return 1
}
}
class Fruits: Topping {
override class func getCost() -> Int {
return 2
}
}
class IceCream {
var nuts: Int = 0
var fruits: Int = 0
var initialCost = 5
func getCost() -> Int {
return initialCost
+ nuts * Nuts.getCost()
+ fruits * Fruits.getCost()
}
}
이 때 문제점: 새로운 Topping 이 추가될 때마다 IceCream class 의 property 와 getCost method 가 수정되어야 한다.
수정 버전:
class ToppingDecorator: IceCream {
}
class Nuts: ToppingDecorator {
private var iceCream: IceCream!
init(iceCream: IceCream) {
super.init()
self.iceCream = iceCream
}
override func getCost() -> Int {
return super.getCost() + 1
}
}
class Fruits: ToppingDecorator {
private var iceCream: IceCream!
init(iceCream: IceCream) {
super.init()
self.iceCream = iceCream
}
override func getCost() -> Int {
return super.getCost() + 2
}
}
class IceCream {
func getCost() -> Int {
return 5
}
}
let iceCream = IceCream()
let iceCreamWithNuts = Nuts(iceCream: iceCream)
let iceCreamWithNutsAndFruits = Fruits(iceCream: iceCreamWithNuts)
- Category
- Delegation