装饰模式使用对象组合的方式动态改变或增加对象行为。Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式。使用匿名组合,在装饰器中不必显式定义转调原对象方法。

设计模式

Go 设计模式- 装饰器模式_装饰器模式在这里插入图片描述

装饰器模式

装饰器模式主要解决继承关系过于复杂的问题,通过组合来代替继承,给原始类添加增强功能,这也是判断装饰器的一个重要依据,除此之外,装饰器还有一个特点,可以对原始类嵌套使用多个装饰器,为了满足这样的需求,在设计的时候,装饰器类需要跟原始继承同步的抽象类或者接口。

Java IO 通过4个基类,扩展出很多子类, 具体如下:Go 设计模式- 装饰器模式_装饰器模式_02

装饰器模式相对于简单的组合关系,有如下特殊点:

  • 装饰器类和原始类继承相同的父类,我们可以对原始类嵌套多个装饰器类。
  • 装饰器类是对功能的增强,这也是装饰器模式应用场景的一个重要特点。

应用场景

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。

代码

package decorator

type Component interface {
Calc() int
}

type ConcreteComponent struct{}

func (*ConcreteComponent) Calc() int {
return 0
}

type MulDecorator struct {
Component
num int
}

func WarpMulDecorator(c Component, num int) Component {
return &MulDecorator{
Component: c,
num: num,
}
}

func (d *MulDecorator) Calc() int {
return d.Component.Calc() * d.num
}

type AddDecorator struct {
Component
num int
}

func WarpAddDecorator(c Component, num int) Component {
return &AddDecorator{
Component: c,
num: num,
}
}

func (d *AddDecorator) Calc() int {
return d.Component.Calc() + d.num
}

测试用例

package decorator

import (
"fmt"
"testing"
)

func TestExampleDecorator(t *testing.T) {
var c Component = &ConcreteComponent{}
c = WarpAddDecorator(c, 10)
c = WarpMulDecorator(c, 8)
res := c.Calc()

fmt.Printf("res %d\n", res)
// Output:
// res 80
}

运行结果

=== RUN   TestExampleDecorator
res 80
--- PASS: TestExampleDecorator (0.00s)
PASS


欢迎关注公众号:程序员开发者社区

Go 设计模式- 装饰器模式_开发者社区_03

关注我们,了解更多


参考资料