装饰器模式vs适配器模式 2023-01-10

2023-01-09  本文已影响0人  9_SooHyun

装饰器模式vs适配器模式

它们都属于【包装模式】

适配器模式

适配器的作用就是将一个接口适配到另一个接口,将一类接口转换为另一类接口

装饰器模式

pre knowledge:
函数也是一个对象。而且函数对象可以赋值给变量,所以,通过变量也能调用该函数

// golang
myPrint := fmt.Printf
myPrint("hhh")

// python
>>> def now():
...     print('2015-3-25')
...
>>> f = now
>>> f()
2015-3-25

装饰器装饰的对象是函数\方法。函数\方法使用方式不变,但内部功能更加完善
装饰器模式不是要改变被装饰对象的接口,而是恰恰要保持原有的接口,但是增强内部功能

装饰器的实现和闭包是分不开的

使用装饰器通常分为2步:实现具体装饰器 + 调用装饰器
调用装饰器,最简朴的方式就是直接调用该装饰器方法
另外,不同语言可能对装饰器的调用可能做了语法糖封装。如python调用装饰器,当然可以直接做函数调用,但更常见的是使用@语法糖

以golang为例,看下装饰器的实现和调用

// 定义一类装饰器 装饰器不会改变函数签名
// attention: http.HandlerFunc in, http.HandlerFunc out
type DecoratorHandler func(http.HandlerFunc) http.HandlerFunc

// 实现一个DecoratorHandler: VerifyHeader. 
// attention: http.HandlerFunc in, http.HandlerFunc out
func VerifyHeader(h http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("token")
        if token == "" {
            fmt.Fprintf(w,r.URL.Path +" response: Not Logged in")
            return
        }
        // 返回的func引用了入参h,func于是成为闭包
        h(w,r)
    }
}


// use DecoratorHandler to decorate HandlerFunc
// 实际上decors是通过functional options的方式执行函数调用从而完成装饰的
func MiddlewareHandlerFunc(hp http.HandlerFunc, decors ...DecoratorHandler) http.HandlerFunc {
    // 注意,需要倒序装饰,不然业务逻辑错乱
    for d := range decors {
        dp := decors[len(decors)-1-d]
        // 直接做最简单的函数调用来完成装饰
        hp = dp(hp)
    }
    return hp
}


func Pong(w http.ResponseWriter, r *http.Request)  {
    fmt.Fprintf(w,r.URL.Path +"response: pong")
    return
}


func main()  {
    http.HandleFunc("/api/asong/ping",MiddlewareHandlerFunc(Pong,VerifyHeader))
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}
上一篇下一篇

猜你喜欢

热点阅读