装饰器模式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)
}
}