装饰器模式
装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承,给原始类添加增强功能。这也是判断是否该用装饰器模式的一个重要的依据。除此之外,装饰器模式还有一个特点,那就是可以对原始类嵌套使用多个装饰器。为了满足这样的需求,在设计的时候,装饰器类需要跟原始类继承相同的抽象类或者接口。
// 装饰者模式:在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用
package main
import "fmt"
type IA interface {
f()
}
// class A
type A struct{}
func NewA() A {
return A{}
}
// A类实现了IA接口
func (a A) f() {
fmt.Println("original function")
}
// class ADecorator,A类的装饰器类,组合了A类
type ADecorator struct {
a A
}
func NewADecorator(a A) ADecorator {
return ADecorator{a: a}
}
// 装饰器类和A类实现相同的接口,并进行了增强
func (ad ADecorator) f() {
fmt.Println("decorator A start")
// 功能增强代码
ad.a.f()
// 功能增强代码
fmt.Println("decorator A end")
}
// A的装饰器类的装饰器,即嵌套装饰
type BDecorator struct {
ad ADecorator
}
func NewBDecorator(ad ADecorator) BDecorator {
return BDecorator{ad: ad}
}
func (bd BDecorator) f() {
fmt.Println("decorator B start")
// 功能增强代码
bd.ad.f()
// 功能增强代码
fmt.Println("decorator B end")
}
func main() {
a := NewA()
// 装饰器嵌套
ad := NewADecorator(a)
bd := NewBDecorator(ad)
// 还可以通过继续嵌套来组合能力(把多个装饰器类的能力组合在一起)
bd.f()
}
实际应该组合接口,并且返回接口,这样才能支持更加灵活的嵌套
package main
import "fmt"
type IA interface {
f()
}
type A struct {
}
func newA() A {
return A{}
}
func (a A) f() {
fmt.Println("i'm A")
}
type OneDecorator struct {
A IA // 组合一个接口,故可以装饰实现了IA接口的类
}
func (ad OneDecorator) f() {
fmt.Println("one decorator start")
ad.A.f() // 委托,执行被装饰类的逻辑
fmt.Println("one decorator end")
}
func newOneDecorator(A IA) IA { // 接收一个接口对其进行装饰,返回的也是接口,因此可以继续被其他装饰类装饰,实现嵌套装饰
return OneDecorator{A: A}
}
type TwoDecorator struct {
A IA // 组合一个接口,故可以装饰实现了IA接口的类
}
func (ad TwoDecorator) f() {
fmt.Println("two decorator start")
ad.A.f() // 委托,执行被装饰类的逻辑
fmt.Println("two decorator end")
}
func newTwoDecorator(A IA) IA { // 接收一个接口对其进行装饰,返回的也是接口,因此可以继续被其他装饰类装饰,实现嵌套装饰
return TwoDecorator{A: A}
}
func useDecorator() {
a := newA()
oneDecorator := newOneDecorator(a)
towDecorator := newTwoDecorator(oneDecorator)
towDecorator.f()
}
func main() {
useDecorator()
}