你還記得小時候玩的樂高嗎?一塊一塊的組裝起來,每塊都增加了更多的功能。裝飾者模式也是這樣,給你一種疊加功能的感覺,但卻不會搞亂原有的設計。
裝飾者模式是一種結構型模式,它允許你動態地、一層一層地新增職責到物件上。你可以想像成給咖啡加料,今天想加牛奶,明天加糖,後天加摩卡,所有的組合都可以!
先從簡單的咖啡開始:
package main
import "fmt"
type Beverage interface {
Description() string
Cost() float64
}
type Coffee struct{}
func (c *Coffee) Description() string {
return "基本咖啡"
}
func (c *Coffee) Cost() float64 {
return 5.0
}
type MilkDecorator struct {
beverage Beverage
}
func (m *MilkDecorator) Description() string {
return m.beverage.Description() + " + 牛奶"
}
func (m *MilkDecorator) Cost() float64 {
return m.beverage.Cost() + 1.5
}
這邊你可以看到,MilkDecorator
是如何把牛奶加入咖啡的。現在,我們來看如何用回調函數擴展這個功能:
type ExtraFeature func(Beverage) Beverage
func WithCaramel(b Beverage) Beverage {
return &CaramelDecorator{beverage: b}
}
type CaramelDecorator struct {
beverage Beverage
}
func (c *CaramelDecorator) Description() string {
return c.beverage.Description() + " + 焦糖"
}
func (c *CaramelDecorator) Cost() float64 {
return c.beverage.Cost() + 2.0
}
func main() {
coffee := &Coffee{}
fmt.Println(coffee.Description(), "$", coffee.Cost())
// 使用裝飾者加牛奶
milkCoffee := &MilkDecorator{beverage: coffee}
fmt.Println(milkCoffee.Description(), "$", milkCoffee.Cost())
// 使用回調函數加焦糖
caramelCoffee := WithCaramel(coffee)
fmt.Println(caramelCoffee.Description(), "$", caramelCoffee.Cost())
}
看到了嗎?現在,只要透過回調函數,就能輕鬆地把焦糖功能加到咖啡上!
裝飾者模式就像樂高,一塊一塊組裝,同時確保每塊都有其功能。在程式裡,這意味著我們不會修改原有的代碼,但仍然可以輕鬆地新增新功能。這也像是我們生活中的習慣,一層一層地疊加,構建出豐富多彩的人生。所以,下次寫代碼時,不妨想想裝飾者模式,看看它能為你帶來哪些驚喜!