跳转到内容

Go 装饰器模式

来自代码酷
Admin留言 | 贡献2025年4月29日 (二) 04:41的版本 (Page creation by admin bot)

(差异) ←上一版本 | 已核准修订 (差异) | 最后版本 (差异) | 下一版本→ (差异)

Go装饰器模式[编辑 | 编辑源代码]

装饰器模式(Decorator Pattern)是一种结构型设计模式,允许在不修改原有对象的情况下动态地扩展其功能。在Go语言中,由于缺乏类继承机制,装饰器模式通常通过组合和接口来实现。它特别适用于需要为对象添加额外行为而又不改变其结构的场景。

基本概念[编辑 | 编辑源代码]

装饰器模式的核心思想是:

  • 定义一个基础接口,表示被装饰对象的类型。
  • 创建具体的实现类,实现基础接口。
  • 创建装饰器结构体,同样实现基础接口,并包含一个基础接口类型的成员变量。
  • 在装饰器的方法中,调用成员变量的方法,并在其前后添加额外的行为。

数学上可以表示为:若原始函数为f(x),装饰后的函数为g(f(x)),其中g是装饰逻辑。

Go实现示例[编辑 | 编辑源代码]

以下是一个简单的Go装饰器示例,展示如何为函数添加日志功能:

package main

import (
	"fmt"
	"time"
)

// 基础接口
type Worker interface {
	DoWork() string
}

// 具体实现
type BasicWorker struct{}

func (b *BasicWorker) DoWork() string {
	return "Basic work done"
}

// 日志装饰器
type LoggingDecorator struct {
	worker Worker
}

func (l *LoggingDecorator) DoWork() string {
	start := time.Now()
	result := l.worker.DoWork()
	end := time.Now()
	
	fmt.Printf("Work started at: %v\n", start)
	fmt.Printf("Work result: %s\n", result)
	fmt.Printf("Work ended at: %v\n", end)
	fmt.Printf("Duration: %v\n", end.Sub(start))
	
	return result
}

func main() {
	basic := &BasicWorker{}
	decorated := &LoggingDecorator{worker: basic}
	
	fmt.Println("Basic worker:")
	fmt.Println(basic.DoWork())
	
	fmt.Println("\nDecorated worker:")
	decorated.DoWork()
}

输出结果:

Basic worker:
Basic work done

Decorated worker:
Work started at: 2023-05-15 10:30:00.123456 +0800 CST m=+0.000000001
Work result: Basic work done
Work ended at: 2023-05-15 10:30:00.123457 +0800 CST m=+0.000000002
Duration: 1ns

装饰器链[编辑 | 编辑源代码]

可以创建多个装饰器并将它们链接起来,每个装饰器添加不同的功能:

// 计时装饰器
type TimingDecorator struct {
	worker Worker
}

func (t *TimingDecorator) DoWork() string {
	start := time.Now()
	result := t.worker.DoWork()
	fmt.Printf("Operation took: %v\n", time.Since(start))
	return result
}

func main() {
	basic := &BasicWorker{}
	decorated := &TimingDecorator{
		worker: &LoggingDecorator{worker: basic},
	}
	
	decorated.DoWork()
}

函数装饰器[编辑 | 编辑源代码]

在Go中,函数是一等公民,可以直接装饰函数:

type WorkerFunc func() string

func Logging(f WorkerFunc) WorkerFunc {
	return func() string {
		fmt.Println("Before execution")
		result := f()
		fmt.Println("After execution")
		return result
	}
}

func main() {
	basic := func() string {
		return "Basic function work"
	}
	
	decorated := Logging(basic)
	fmt.Println(decorated())
}

实际应用场景[编辑 | 编辑源代码]

1. 日志记录:在不修改业务逻辑的情况下添加日志 2. 性能监控:测量函数执行时间 3. 缓存:为昂贵操作添加缓存层 4. 认证/授权:在执行业务逻辑前检查权限 5. 重试机制:为可能失败的操作添加自动重试

HTTP中间件案例[编辑 | 编辑源代码]

HTTP中间件是装饰器模式的典型应用:

package main

import (
	"fmt"
	"net/http"
)

type Handler func(http.ResponseWriter, *http.Request)

func LoggingMiddleware(next Handler) Handler {
	return func(w http.ResponseWriter, r *http.Request) {
		fmt.Printf("Request: %s %s\n", r.Method, r.URL.Path)
		next(w, r)
	}
}

func AuthMiddleware(next Handler) Handler {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Authorization") == "" {
			http.Error(w, "Unauthorized", http.StatusUnauthorized)
			return
		}
		next(w, r)
	}
}

func mainHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "Main handler executed")
}

func main() {
	handler := LoggingMiddleware(AuthMiddleware(mainHandler))
	
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

类图表示[编辑 | 编辑源代码]

classDiagram class Worker { <<interface>> DoWork() string } class BasicWorker { DoWork() string } class LoggingDecorator { -worker Worker DoWork() string } class TimingDecorator { -worker Worker DoWork() string } Worker <|-- BasicWorker Worker <|-- LoggingDecorator Worker <|-- TimingDecorator LoggingDecorator o-- Worker TimingDecorator o-- Worker

优缺点[编辑 | 编辑源代码]

优点:

  • 比继承更灵活,可以在运行时添加或移除功能
  • 符合开闭原则,无需修改现有代码就能扩展功能
  • 可以组合多个装饰器实现复杂功能

缺点:

  • 可能引入许多小类,增加系统复杂度
  • 装饰器栈过深可能影响性能
  • 调试可能变得困难,因为行为分布在多个装饰器中

总结[编辑 | 编辑源代码]

Go装饰器模式提供了一种强大的方式来扩展对象功能而不修改其结构。通过组合和接口,Go开发者可以实现类似其他语言中通过继承获得的功能扩展。这种模式特别适合需要动态添加功能的场景,如中间件、日志、监控等。理解装饰器模式有助于编写更灵活、可维护的Go代码。