GoLang 設計模型 — Decorator Pattern
5 min readAug 16, 2023
中文為裝飾者模式(Decorator Pattern),是指在不改變現有物件的結構下,動態地增加一些職責外的功能或是驗證。可以想像該模式會長得像同心圓,當使用者使用該物件時,需要經過一層一層驗證方可觸碰到最內部的物件核心。
此模式中的角色有:
- 元件(Component):是個介面,其中會定義 Decorator們該執行些什麼方法。
- 裝飾器(Decorator):會實作Component 中定義好的方法,並給具體上該裝飾器本身職責該做的事情。
使用場景
- 如果開發者不想要再更動既有的物件情況下,想針對他新增些新功能或是驗證即可使用此模型。
- 如果透過繼承來擴展物件行為的方案難以呈現,即可使用此模型。
- Decorator 可以將商務邏輯依照層次結構進行分類,使用者可以透過介面去實作 Decorator 行為,且不同的Decorator可以相互組合。
Code 演練
其中我們定義了兩個 Decorator A & B,我們各自在 Decorator裡實作了 Operation並透過 SetComponent 來定義好 Decorator順序。
- 專案架構
- Component
package Components
import "fmt"
type Component interface {
Operation()
}
type ConcreteComponent struct {
}
func (c *ConcreteComponent) Operation() {
fmt.Println("ConcreteComponent operating")
}
- Decorator-A
package decorators
import (
"decorator/Components"
"fmt"
)
type DecoratorA struct {
component Components.Component
}
func (da *DecoratorA) SetComponent(com Components.Component) {
da.component = com
}
func (da *DecoratorA) Operation() {
da.component.Operation()
da.InpendentMethod()
}
func (da *DecoratorA) InpendentMethod() {
fmt.Println("Inpendent Method of Decorator A")
}
- Decorator-B
package decorators
import (
"decorator/Components"
"fmt"
)
type DecoratorB struct {
component Components.Component
}
func (db *DecoratorB) SetComponent(component Components.Component) {
db.component = component
}
func (db *DecoratorB) Operation() {
db.component.Operation()
fmt.Println(db.String())
}
func (db *DecoratorB) String() string {
return "Independent method of DecoratorB"
}
- main.go
package main
import (
"decorator/Components"
decorators "decorator/Decorators"
)
func main() {
concreteComponent := Components.ConcreteComponent{}
decoratorA := decorators.DecoratorA{}
decoratorB := decorators.DecoratorB{}
// every decorator implements Component interface
decoratorA.SetComponent(&concreteComponent)
decoratorB.SetComponent(&decoratorA)
decoratorB.Operation()
}
- 輸出效果
優缺點比較
優點
- 為了擴展功能提出了一個靈活擴展的方案
- 允許在運行時進行修該,而非直接修改原有程式碼
- 支持 OCP (Opened-Closed-Principle)
缺點
- 會建立出許多小物件,過度使用會導致專案架構複雜
- 使用端嚴重依賴Componet的具體實現類型
- 讓裝飾器跟蹤其他裝飾器,可能會很複雜