dushaoshuai / dushaoshuai.github.io

https://www.shuai.host
0 stars 0 forks source link

Decorator(Wrapper) #78

Open dushaoshuai opened 1 year ago

dushaoshuai commented 1 year ago

装饰器模式使用装饰器(decorator)包装对象(concrete component),动态地修饰其行为。装饰器和被装饰对象实现相同的接口(Component),因此可以无限次地对被装饰对象进行修饰。

Context

context 包使用了装饰器模式。

Context 是一个接口:

type Context interface {
    Deadline() (deadline time.Time, ok bool)
    Done() <-chan struct{}
    Err() error
    Value(key any) any
}

emptyCtx

emptyCtx 实现了 Context,但它又好像什么也没做:

type emptyCtx int

func (*emptyCtx) Deadline() (deadline time.Time, ok bool) { return }
func (*emptyCtx) Done() <-chan struct{} { return nil }
func (*emptyCtx) Err() error { return nil }
func (*emptyCtx) Value(key any) any { return nil }

Background()TODO() 都返回 *emptyCtx

var (
    background = new(emptyCtx)
    todo       = new(emptyCtx)
)

func Background() Context { return background } 
func TODO() Context { return todo }

emptyCtx 为其它的装饰器提供了一个实现 Context 的基础。

cancelCtx

type cancelCtx struct {
    Context
    // ...
}

cancelCtx 自己实现了 Value(key any) anyDone() <-chan struct{}Err() error 三个方法,将 Deadline() (deadline time.Time, ok bool) 方法委托给嵌入的匿名字段 Context,因此它实现了 Context

WithCancel()WithCancelCause() 都返回 *cancelCtx

func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
    c := withCancel(parent)
    return c, func() { c.cancel(true, Canceled, nil) }
}

func WithCancelCause(parent Context) (ctx Context, cancel CancelCauseFunc) {
    c := withCancel(parent)
    return c, func(cause error) { c.cancel(true, Canceled, cause) }
}

timerCtx

type timerCtx struct {
    *cancelCtx
    // ...
}

timerCtx 自己实现了 Deadline() (deadline time.Time, ok bool) 方法,将其它三个方法委托给嵌入的匿名字段 cancelCtx

WithDeadline()WithTimeout() 都返回 *timeCtx

func WithDeadline(parent Context, d time.Time) (Context, CancelFunc) {
    // ...
    c := &timerCtx{
        cancelCtx: newCancelCtx(parent),
    deadline:  d,
    }
    // ...
    return c, func() { c.cancel(true, Canceled, nil) }
}

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
    return WithDeadline(parent, time.Now().Add(timeout))
}

valueCtx

type valueCtx struct {
    Context
    key, val any
}

valueCtx 自己实现了 Value(key any) any 方法,将其它方法委托给嵌入的匿名字段 Context

WithValue() 返回 *valueCtx

func WithValue(parent Context, key, val any) Context {
    // ...
    return &valueCtx{parent, key, val}
}

return interface instead of concrete implementation

注意所有对一个 Context 进行装饰返回另一个 Context 的函数,返回的都是接口而不是具体的实现。