前提:
创建型模式 : 就是专门用来拿到实例化对象的
装饰器模式是一种结构型模式,强调的是结构,不同于创建型模式
先了解代理模式的代码风格,因为装饰器模式是在此基础上改进的
下面附上代理模式的代码:
type task interface {
doHomeWork()
}
type zhangSan struct{}
func (z *zhangSan) doHomeWork() {
fmt.Println("张三的作业")
}
type liSi struct{}
func (l *liSi) doHomeWork() {
fmt.Println("李四的作业")
}
type wangWu struct{}
func (w *wangWu) doHomeWork() {
fmt.Println("王五的作业")
}
type writer struct {
t task //这里就体现了代理模式的思想,就相当于在说,写手有了写作业的功能
//task本身就是引用类型了,所以不写成 t *task
}
func (w *writer) doHomeWork() {
fmt.Println("写手开始代写作业")
w.t.doHomeWork()
w.answerQuestion()
}
// 甚至于写手还会提供答疑
func (w *writer) answerQuestion() {
fmt.Println("写手开始答疑")
w.t.doHomeWork()
}
func newClient(t task) task {
return &writer{t}
}
func main() {
z := &zhangSan{}
c := newClient(z)
c.doHomeWork()
}
可以发现,写手组合了 task 接口以后,就让写手实现接口,并且绑定新的函数
而装饰器模式是把 task 接口不直接组合进写手结构体,而是组合进一个中转的decorator结构体
再使用新的结构体去继承decorator,让新的结构体实现接口,并且绑定新的函数
为了更加灵活使用装饰器模式,下面用一个新的例子:
package main
import "fmt"
type art interface {
//可以改变卡片的行为就可以叫做艺术
changeCard()
}
// 颜料
type pigment struct{}
func (p *pigment) changeCard() {
fmt.Println("颜料可以改变卡片颜色")
}
// 雕刻
type engrave struct{}
func (e *engrave) changeCard() {
fmt.Println("雕刻可以美化卡片的外层")
}
// 如果是代理模式,那么这里就已经是代理结构体了
// 而装饰器模式就是在代理模式的基础上,把【代理结构体】写成【装饰结构体】
// 然后按照需求去继承装饰结构体
// 装饰器模式相较于代理模式更加的灵活,可以任意顺序的叠加功能
type decorator struct {
a art
}
// 折纸可以在颜料,雕刻的基础上进一步塑形,所以继承了艺术
type fold struct {
decorator
}
func (f *fold) changeCard() {
f.a.changeCard()
fmt.Println("折纸")
}
func NewFold(a art) art {
return &fold{decorator{a}}
}
// 剪纸可以在颜料,雕刻的基础上进一步留主去繁,所以继承了艺术
type cut struct {
decorator
}
func (c *cut) changeCard() {
c.a.changeCard()
fmt.Println("剪纸")
}
func NewCut(a art) art {
return &cut{decorator{a}}
}
func main() {
f := NewFold(&pigment{})
f.changeCard()//上颜料,再折纸
c := NewCut(&engrave{})
c.changeCard()//先雕刻,再剪纸
v := NewCut(f)
v.changeCard()//上颜料,再折纸,最后剪纸
}