装饰器模式
装饰器模式是一种结构型设计模式,它允许在运行时动态地添加对象的新行为。这种模式通过将对象包装在装饰器类的对象中来实现。
装饰器模式通常用于以下几种情况:
- 当你需要在不修改现有对象代码的情况下扩展对象的行为时。装饰器模式提供了一种灵活的方法来混合和匹配新行为,而不需要创建大量的子类。
- 当你需要在运行时动态地添加或删除对象的行为时。由于装饰器模式允许你在运行时包装和解包装对象,所以你可以在运行时改变对象的行为。
- 当你需要将一些行为应用于多个独立的对象时。使用装饰器模式,你可以定义一个通用的装饰器类,并将其应用于多个不同的对象,而不需要为每个对象都定义一个新的子类。
代码示例:
package main
import "net/http"
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", HelloWorld)
mux.HandleFunc("GET /how", HowAreYou)
srv := http.Server{
Addr: ":8080",
Handler: mux,
}
srv.ListenAndServe()
}
func HowAreYou(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("I am fine"))
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("hello world!"))
}
如果我要记录请求的时间和请求日志,可能会这么写:
func HowAreYou(w http.ResponseWriter, r *http.Request) {
now := time.Now()
w.WriteHeader(http.StatusOK)
w.Write([]byte("I am fine"))
log.Printf("url: %s, elase: %v", r.URL, time.Since(now))
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
now := time.Now()
w.WriteHeader(http.StatusOK)
w.Write([]byte("hello world!"))
log.Printf("url: %s, elapsed: %v", r.URL, time.Since(now))
}
但是如果方法很多的话这么写太浪费时间了
这时候就可以使用装饰器模式
package main
import (
"log"
"net/http"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", Logger(HelloWorld))
mux.HandleFunc("GET /how", Logger(HowAreYou))
srv := http.Server{
Addr: ":8080",
Handler: mux,
}
srv.ListenAndServe()
}
type Handler func(w http.ResponseWriter, r *http.Request)
func Logger(handler Handler) Handler {
return func(w http.ResponseWriter, r *http.Request) {
now := time.Now()
handler(w, r)
log.Printf("url: %s, elase: %v", r.URL, time.Since(now))
}
}
func HowAreYou(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("I am fine"))
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("hello world!"))
}
或者
package main
import (
"log"
"net/http"
"time"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /hello", HelloWorld)
mux.HandleFunc("GET /how", HowAreYou)
srv := http.Server{
Addr: ":8080",
Handler: Logger(mux),
}
srv.ListenAndServe()
}
func Logger(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
now := time.Now()
next.ServeHTTP(w, r)
log.Printf("url: %s, elase: %v", r.URL, time.Since(now))
}
return http.HandlerFunc(fn)
}
func HowAreYou(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("I am fine"))
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("hello world!"))
}