golang设计模式-装饰器模式

装饰器模式

装饰器模式是一种结构型设计模式,它允许在运行时动态地添加对象的新行为。这种模式通过将对象包装在装饰器类的对象中来实现。

装饰器模式通常用于以下几种情况:

  • 当你需要在不修改现有对象代码的情况下扩展对象的行为时。装饰器模式提供了一种灵活的方法来混合和匹配新行为,而不需要创建大量的子类。
  • 当你需要在运行时动态地添加或删除对象的行为时。由于装饰器模式允许你在运行时包装和解包装对象,所以你可以在运行时改变对象的行为。
  • 当你需要将一些行为应用于多个独立的对象时。使用装饰器模式,你可以定义一个通用的装饰器类,并将其应用于多个不同的对象,而不需要为每个对象都定义一个新的子类。

代码示例:

go 复制代码
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!"))
}

如果我要记录请求的时间和请求日志,可能会这么写:

go 复制代码
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))
}

但是如果方法很多的话这么写太浪费时间了

这时候就可以使用装饰器模式

go 复制代码
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!"))
}

或者

go 复制代码
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!"))
}
相关推荐
llwszx4 小时前
【Java/Go后端手撸原生Agent(第九篇):Plan-and-Execute规划模式——从“走一步看一步“到“先谋后动“】
java·python·golang·agent开发·plan模式·规划执行模式
灯澜忆梦6 小时前
GO_网络编程---文件传输实战
网络·golang·php
北冥you鱼8 小时前
Go 语言新手扫盲:指针 * 和 & 使用场景详解
开发语言·后端·golang
第一个传播学9 小时前
赛博朋克2077修改器下载及其用法
设计模式
Wang's Blog10 小时前
Go-Zero项目开发17: IM私聊功能实现与消息存储设计
开发语言·后端·golang
名字还没想好☜11 小时前
Go 的 select 实战:超时、非阻塞收发与优雅退出的三个套路
开发语言·数据库·golang·go·并发
萧青山12 小时前
2026国标合规:Agent Loop合规设计模式的6种循环架构(GB/Z 185.6+Python)
python·设计模式·agent loop·gb/z 185·国标合规
编程序的员12 小时前
使用OpenTelemetry来监控GoLang应用
运维·golang·monitoring·apm·opentelemetry
ttwuai1 天前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
杨充1 天前
11.DDD与战术建模
设计模式·开源·代码规范