BUILD · THINK · WRITE
在暗夜里写清楚代码
记录 Go、后端工程、并发编程、设计模式与开发思考。

Go 语言实现 23 种常见设计模式

Go 语言实现 23 种常见设计模式

设计模式是对常见软件设计问题的可复用解法。经典 GoF 设计模式共有 23 种,可以分为三类:

  • 创建型模式:关注对象如何创建。
  • 结构型模式:关注类或对象如何组合成更大的结构。
  • 行为型模式:关注对象之间如何协作、通信和分配职责。

Go 没有类继承,更多依赖接口、组合、函数和闭包来表达设计模式。下面的示例都尽量使用 Go 的惯用写法。

一、创建型模式

1. 单例模式 Singleton

单例模式保证一个类型在程序中只有一个实例,并提供全局访问点。Go 中通常使用 sync.Once 实现线程安全的懒加载。

适用场景:

  • 全局配置。
  • 日志器。
  • 数据库连接池管理器。
package singleton

import "sync"

type Config struct {
	DSN string
}

var (
	instance *Config
	once     sync.Once
)

func GetConfig() *Config {
	once.Do(func() {
		instance = &Config{DSN: "user:pass@tcp(localhost:3306)/app"}
	})
	return instance
}

补充:简单工厂 Simple Factory

简单工厂不属于 GoF 23 种之一,但它很常用。它把创建对象的逻辑集中到一个函数中,调用方只需要传入类型标识即可。

适用场景:

  • 对象创建逻辑简单。
  • 调用方不想知道具体结构体。
package simplefactory

import "fmt"

type Shape interface {
	Draw() string
}

type Circle struct{}

func (Circle) Draw() string {
	return "draw circle"
}

type Rectangle struct{}

func (Rectangle) Draw() string {
	return "draw rectangle"
}

func NewShape(kind string) (Shape, error) {
	switch kind {
	case "circle":
		return Circle{}, nil
	case "rectangle":
		return Rectangle{}, nil
	default:
		return nil, fmt.Errorf("unknown shape: %s", kind)
	}
}

2. 工厂方法 Factory Method

工厂方法把对象创建延迟到具体工厂中。调用方依赖工厂接口,而不是依赖具体产品。

适用场景:

  • 需要创建一系列同类产品。
  • 创建逻辑可能随产品类型扩展。
package factorymethod

type Button interface {
	Render() string
}

type WindowsButton struct{}

func (WindowsButton) Render() string {
	return "render windows button"
}

type MacButton struct{}

func (MacButton) Render() string {
	return "render mac button"
}

type ButtonFactory interface {
	CreateButton() Button
}

type WindowsFactory struct{}

func (WindowsFactory) CreateButton() Button {
	return WindowsButton{}
}

type MacFactory struct{}

func (MacFactory) CreateButton() Button {
	return MacButton{}
}

func RenderDialog(factory ButtonFactory) string {
	return factory.CreateButton().Render()
}

3. 抽象工厂 Abstract Factory

抽象工厂用于创建一组相关或相互依赖的对象。它比工厂方法更强调“产品族”。

适用场景:

  • UI 组件需要按操作系统成套切换。
  • 数据库驱动、缓存组件、消息组件需要按环境成套创建。
package abstractfactory

type Button interface {
	Paint() string
}

type Checkbox interface {
	Check() string
}

type GUIFactory interface {
	NewButton() Button
	NewCheckbox() Checkbox
}

type WinButton struct{}

func (WinButton) Paint() string {
	return "windows button"
}

type WinCheckbox struct{}

func (WinCheckbox) Check() string {
	return "windows checkbox"
}

type WinFactory struct{}

func (WinFactory) NewButton() Button {
	return WinButton{}
}

func (WinFactory) NewCheckbox() Checkbox {
	return WinCheckbox{}
}

type MacButton struct{}

func (MacButton) Paint() string {
	return "mac button"
}

type MacCheckbox struct{}

func (MacCheckbox) Check() string {
	return "mac checkbox"
}

type MacFactory struct{}

func (MacFactory) NewButton() Button {
	return MacButton{}
}

func (MacFactory) NewCheckbox() Checkbox {
	return MacCheckbox{}
}

4. 建造者模式 Builder

建造者模式把复杂对象的构建过程拆成多个步骤,让同样的构建过程可以创建不同表示。

Go 中常见写法是链式调用或函数式选项。

适用场景:

  • 对象字段很多。
  • 构建过程需要校验、默认值或顺序。
package builder

type Server struct {
	Host    string
	Port    int
	TLS     bool
	Timeout int
}

type ServerBuilder struct {
	server Server
}

func NewServerBuilder() *ServerBuilder {
	return &ServerBuilder{
		server: Server{
			Host:    "127.0.0.1",
			Port:    8080,
			Timeout: 30,
		},
	}
}

func (b *ServerBuilder) Host(host string) *ServerBuilder {
	b.server.Host = host
	return b
}

func (b *ServerBuilder) Port(port int) *ServerBuilder {
	b.server.Port = port
	return b
}

func (b *ServerBuilder) EnableTLS() *ServerBuilder {
	b.server.TLS = true
	return b
}

func (b *ServerBuilder) Timeout(seconds int) *ServerBuilder {
	b.server.Timeout = seconds
	return b
}

func (b *ServerBuilder) Build() Server {
	return b.server
}

5. 原型模式 Prototype

原型模式通过复制已有对象来创建新对象,避免重复初始化复杂对象。

适用场景:

  • 创建成本高。
  • 需要保留默认配置并快速复制。
  • 对象结构复杂,不想重新走构造流程。
package prototype

type Cloneable interface {
	Clone() Cloneable
}

type Document struct {
	Title  string
	Tags   []string
	Author string
}

func (d Document) Clone() Cloneable {
	tags := make([]string, len(d.Tags))
	copy(tags, d.Tags)

	return Document{
		Title:  d.Title,
		Tags:   tags,
		Author: d.Author,
	}
}

二、结构型模式

6. 适配器模式 Adapter

适配器模式把一个已有接口转换成客户端期望的接口。

适用场景:

  • 第三方库接口和业务接口不一致。
  • 需要兼容旧系统。
package adapter

type Payment interface {
	Pay(amount int) string
}

type LegacyAlipay struct{}

func (LegacyAlipay) SendPayment(cents int) string {
	return "legacy alipay paid"
}

type AlipayAdapter struct {
	legacy LegacyAlipay
}

func NewAlipayAdapter(legacy LegacyAlipay) Payment {
	return AlipayAdapter{legacy: legacy}
}

func (a AlipayAdapter) Pay(amount int) string {
	return a.legacy.SendPayment(amount * 100)
}

7. 桥接模式 Bridge

桥接模式把抽象部分和实现部分分离,使二者可以独立变化。

适用场景:

  • 一个对象有多个变化维度。
  • 不希望通过大量组合类型造成爆炸。
package bridge

type Renderer interface {
	RenderCircle(radius float64) string
}

type VectorRenderer struct{}

func (VectorRenderer) RenderCircle(radius float64) string {
	return "draw circle with vector"
}

type RasterRenderer struct{}

func (RasterRenderer) RenderCircle(radius float64) string {
	return "draw circle with raster"
}

type Circle struct {
	Radius   float64
	renderer Renderer
}

func NewCircle(radius float64, renderer Renderer) Circle {
	return Circle{Radius: radius, renderer: renderer}
}

func (c Circle) Draw() string {
	return c.renderer.RenderCircle(c.Radius)
}

8. 组合模式 Composite

组合模式把对象组织成树形结构,让调用方以一致方式处理单个对象和对象集合。

适用场景:

  • 文件系统。
  • 菜单树。
  • 组织架构。
package composite

type Node interface {
	Name() string
	Size() int
}

type File struct {
	name string
	size int
}

func NewFile(name string, size int) File {
	return File{name: name, size: size}
}

func (f File) Name() string {
	return f.name
}

func (f File) Size() int {
	return f.size
}

type Directory struct {
	name     string
	children []Node
}

func NewDirectory(name string) *Directory {
	return &Directory{name: name}
}

func (d *Directory) Add(node Node) {
	d.children = append(d.children, node)
}

func (d *Directory) Name() string {
	return d.name
}

func (d *Directory) Size() int {
	total := 0
	for _, child := range d.children {
		total += child.Size()
	}
	return total
}

9. 装饰器模式 Decorator

装饰器模式在不修改原对象的情况下,动态增强对象行为。

适用场景:

  • 日志、缓存、鉴权、重试。
  • 需要层层叠加能力。
package decorator

type Handler interface {
	Handle(request string) string
}

type BaseHandler struct{}

func (BaseHandler) Handle(request string) string {
	return "handle " + request
}

type LoggingHandler struct {
	next Handler
}

func NewLoggingHandler(next Handler) Handler {
	return LoggingHandler{next: next}
}

func (h LoggingHandler) Handle(request string) string {
	return "[log] " + h.next.Handle(request)
}

type AuthHandler struct {
	next Handler
}

func NewAuthHandler(next Handler) Handler {
	return AuthHandler{next: next}
}

func (h AuthHandler) Handle(request string) string {
	return "[auth] " + h.next.Handle(request)
}

10. 外观模式 Facade

外观模式为复杂子系统提供一个简单统一的入口。

适用场景:

  • 隐藏复杂流程。
  • 给调用方提供更稳定、更易用的 API。
package facade

type Inventory struct{}

func (Inventory) Reserve(productID string) string {
	return "inventory reserved: " + productID
}

type Payment struct{}

func (Payment) Charge(userID string) string {
	return "payment charged: " + userID
}

type Shipping struct{}

func (Shipping) Ship(productID string) string {
	return "shipping created: " + productID
}

type OrderFacade struct {
	inventory Inventory
	payment   Payment
	shipping  Shipping
}

func NewOrderFacade() OrderFacade {
	return OrderFacade{
		inventory: Inventory{},
		payment:   Payment{},
		shipping:  Shipping{},
	}
}

func (f OrderFacade) PlaceOrder(userID, productID string) []string {
	return []string{
		f.inventory.Reserve(productID),
		f.payment.Charge(userID),
		f.shipping.Ship(productID),
	}
}

11. 享元模式 Flyweight

享元模式通过共享细粒度对象来减少内存消耗。它通常把对象状态分为内部状态和外部状态。

适用场景:

  • 大量相似对象。
  • 对象内部状态可以复用。
package flyweight

type TreeType struct {
	Name  string
	Color string
}

type TreeFactory struct {
	cache map[string]*TreeType
}

func NewTreeFactory() *TreeFactory {
	return &TreeFactory{cache: make(map[string]*TreeType)}
}

func (f *TreeFactory) GetTreeType(name, color string) *TreeType {
	key := name + ":" + color
	if treeType, ok := f.cache[key]; ok {
		return treeType
	}

	treeType := &TreeType{Name: name, Color: color}
	f.cache[key] = treeType
	return treeType
}

type Tree struct {
	X, Y int
	Type *TreeType
}

12. 代理模式 Proxy

代理模式为真实对象提供一个替身,用来控制访问、延迟加载、缓存或增加保护逻辑。

适用场景:

  • 远程代理。
  • 缓存代理。
  • 权限代理。
  • 延迟加载。
package proxy

type Image interface {
	Display() string
}

type RealImage struct {
	filename string
}

func NewRealImage(filename string) RealImage {
	return RealImage{filename: filename}
}

func (i RealImage) Display() string {
	return "display " + i.filename
}

type ImageProxy struct {
	filename string
	real     *RealImage
}

func NewImageProxy(filename string) *ImageProxy {
	return &ImageProxy{filename: filename}
}

func (p *ImageProxy) Display() string {
	if p.real == nil {
		image := NewRealImage(p.filename)
		p.real = &image
	}
	return p.real.Display()
}

三、行为型模式

13. 责任链模式 Chain of Responsibility

责任链模式把请求沿着处理链传递,直到某个处理器处理它为止。

适用场景:

  • HTTP 中间件。
  • 审批流程。
  • 多级校验。
package chain

type Request struct {
	Amount int
}

type Handler interface {
	SetNext(next Handler) Handler
	Handle(request Request) string
}

type BaseHandler struct {
	next Handler
}

func (h *BaseHandler) SetNext(next Handler) Handler {
	h.next = next
	return next
}

func (h *BaseHandler) callNext(request Request) string {
	if h.next == nil {
		return "no handler"
	}
	return h.next.Handle(request)
}

type Manager struct {
	BaseHandler
}

func (m *Manager) Handle(request Request) string {
	if request.Amount <= 1000 {
		return "manager approved"
	}
	return m.callNext(request)
}

type Director struct {
	BaseHandler
}

func (d *Director) Handle(request Request) string {
	if request.Amount <= 10000 {
		return "director approved"
	}
	return d.callNext(request)
}

14. 命令模式 Command

命令模式把请求封装成对象,使请求发送者和执行者解耦。

适用场景:

  • 撤销、重做。
  • 队列任务。
  • 操作日志。
package command

type Command interface {
	Execute() string
}

type Light struct {
	on bool
}

func (l *Light) On() string {
	l.on = true
	return "light on"
}

func (l *Light) Off() string {
	l.on = false
	return "light off"
}

type LightOnCommand struct {
	light *Light
}

func NewLightOnCommand(light *Light) Command {
	return LightOnCommand{light: light}
}

func (c LightOnCommand) Execute() string {
	return c.light.On()
}

type RemoteControl struct {
	command Command
}

func (r *RemoteControl) SetCommand(command Command) {
	r.command = command
}

func (r *RemoteControl) Press() string {
	return r.command.Execute()
}

15. 解释器模式 Interpreter

解释器模式为某种语言或表达式定义语法表示,并提供解释执行的方法。

适用场景:

  • 简单规则引擎。
  • 表达式解析。
  • DSL。
package interpreter

type Expression interface {
	Interpret(context map[string]bool) bool
}

type Variable struct {
	Name string
}

func (v Variable) Interpret(context map[string]bool) bool {
	return context[v.Name]
}

type And struct {
	Left  Expression
	Right Expression
}

func (a And) Interpret(context map[string]bool) bool {
	return a.Left.Interpret(context) && a.Right.Interpret(context)
}

type Or struct {
	Left  Expression
	Right Expression
}

func (o Or) Interpret(context map[string]bool) bool {
	return o.Left.Interpret(context) || o.Right.Interpret(context)
}

16. 迭代器模式 Iterator

迭代器模式提供一种顺序访问集合元素的方法,而不暴露集合内部结构。

Go 中常用 range,但自定义集合仍然可以显式实现迭代器。

适用场景:

  • 自定义集合。
  • 需要统一遍历方式。
package iterator

type Iterator interface {
	HasNext() bool
	Next() string
}

type BookCollection struct {
	books []string
}

func NewBookCollection(books []string) BookCollection {
	return BookCollection{books: books}
}

func (c BookCollection) Iterator() Iterator {
	return &BookIterator{books: c.books}
}

type BookIterator struct {
	books []string
	index int
}

func (i *BookIterator) HasNext() bool {
	return i.index < len(i.books)
}

func (i *BookIterator) Next() string {
	book := i.books[i.index]
	i.index++
	return book
}

17. 中介者模式 Mediator

中介者模式用一个中介对象封装多个对象之间的交互,减少对象之间的直接依赖。

适用场景:

  • 聊天室。
  • 表单组件联动。
  • 多个模块交互复杂。
package mediator

type ChatRoom struct {
	users map[string]*User
}

func NewChatRoom() *ChatRoom {
	return &ChatRoom{users: make(map[string]*User)}
}

func (c *ChatRoom) Register(user *User) {
	c.users[user.Name] = user
	user.room = c
}

func (c *ChatRoom) Send(from, to, message string) string {
	if _, ok := c.users[to]; !ok {
		return "user not found"
	}
	return from + " -> " + to + ": " + message
}

type User struct {
	Name string
	room *ChatRoom
}

func NewUser(name string) *User {
	return &User{Name: name}
}

func (u *User) Send(to, message string) string {
	return u.room.Send(u.Name, to, message)
}

18. 备忘录模式 Memento

备忘录模式在不暴露对象内部实现的情况下保存和恢复对象状态。

适用场景:

  • 撤销。
  • 快照。
  • 历史版本。
package memento

type Memento struct {
	content string
}

type Editor struct {
	content string
}

func (e *Editor) Type(text string) {
	e.content += text
}

func (e *Editor) Content() string {
	return e.content
}

func (e *Editor) Save() Memento {
	return Memento{content: e.content}
}

func (e *Editor) Restore(m Memento) {
	e.content = m.content
}

type History struct {
	stack []Memento
}

func (h *History) Push(m Memento) {
	h.stack = append(h.stack, m)
}

func (h *History) Pop() (Memento, bool) {
	if len(h.stack) == 0 {
		return Memento{}, false
	}

	last := h.stack[len(h.stack)-1]
	h.stack = h.stack[:len(h.stack)-1]
	return last, true
}

19. 观察者模式 Observer

观察者模式定义对象之间的一对多依赖。当主题状态变化时,所有观察者都会收到通知。

适用场景:

  • 事件系统。
  • 消息订阅。
  • UI 状态变化通知。
package observer

type Observer interface {
	Update(message string)
}

type Subject struct {
	observers []Observer
}

func (s *Subject) Attach(observer Observer) {
	s.observers = append(s.observers, observer)
}

func (s *Subject) Notify(message string) {
	for _, observer := range s.observers {
		observer.Update(message)
	}
}

type User struct {
	Name     string
	Messages []string
}

func (u *User) Update(message string) {
	u.Messages = append(u.Messages, u.Name+": "+message)
}

20. 状态模式 State

状态模式让对象在内部状态改变时改变行为,看起来像是改变了对象的类型。

适用场景:

  • 订单状态流转。
  • 工作流。
  • 有限状态机。
package state

type State interface {
	Pay(order *Order) string
	Ship(order *Order) string
}

type Order struct {
	state State
}

func NewOrder() *Order {
	return &Order{state: PendingState{}}
}

func (o *Order) SetState(state State) {
	o.state = state
}

func (o *Order) Pay() string {
	return o.state.Pay(o)
}

func (o *Order) Ship() string {
	return o.state.Ship(o)
}

type PendingState struct{}

func (PendingState) Pay(order *Order) string {
	order.SetState(PaidState{})
	return "order paid"
}

func (PendingState) Ship(order *Order) string {
	return "cannot ship unpaid order"
}

type PaidState struct{}

func (PaidState) Pay(order *Order) string {
	return "already paid"
}

func (PaidState) Ship(order *Order) string {
	order.SetState(ShippedState{})
	return "order shipped"
}

type ShippedState struct{}

func (ShippedState) Pay(order *Order) string {
	return "already shipped"
}

func (ShippedState) Ship(order *Order) string {
	return "already shipped"
}

21. 策略模式 Strategy

策略模式定义一组算法,把每个算法封装起来,并让它们可以互换。

适用场景:

  • 支付方式切换。
  • 排序算法切换。
  • 折扣规则切换。
package strategy

type DiscountStrategy interface {
	Discount(price float64) float64
}

type NoDiscount struct{}

func (NoDiscount) Discount(price float64) float64 {
	return price
}

type PercentageDiscount struct {
	Percent float64
}

func (d PercentageDiscount) Discount(price float64) float64 {
	return price * (1 - d.Percent)
}

type Order struct {
	Price    float64
	strategy DiscountStrategy
}

func NewOrder(price float64, strategy DiscountStrategy) Order {
	return Order{Price: price, strategy: strategy}
}

func (o Order) FinalPrice() float64 {
	return o.strategy.Discount(o.Price)
}

22. 模板方法 Template Method

模板方法定义算法骨架,把某些步骤延迟到具体实现中。

Go 没有继承,通常使用组合和接口表达模板方法。

适用场景:

  • 固定流程中有部分步骤可变。
  • 多种实现共享同一执行顺序。
package templatemethod

type DataMiner interface {
	Open(path string) string
	Extract() string
	Close() string
}

func Mine(path string, miner DataMiner) []string {
	return []string{
		miner.Open(path),
		miner.Extract(),
		miner.Close(),
	}
}

type CSVDataMiner struct{}

func (CSVDataMiner) Open(path string) string {
	return "open csv: " + path
}

func (CSVDataMiner) Extract() string {
	return "extract csv data"
}

func (CSVDataMiner) Close() string {
	return "close csv"
}

type PDFDataMiner struct{}

func (PDFDataMiner) Open(path string) string {
	return "open pdf: " + path
}

func (PDFDataMiner) Extract() string {
	return "extract pdf data"
}

func (PDFDataMiner) Close() string {
	return "close pdf"
}

23. 访问者模式 Visitor

访问者模式把作用于对象结构中各元素的操作封装起来,使得可以在不改变元素类型的前提下新增操作。

适用场景:

  • 对象结构稳定,但操作经常变化。
  • 需要对一组不同类型对象执行不同操作。
package visitor

type Visitor interface {
	VisitCircle(circle Circle) string
	VisitRectangle(rectangle Rectangle) string
}

type Shape interface {
	Accept(visitor Visitor) string
}

type Circle struct {
	Radius float64
}

func (c Circle) Accept(visitor Visitor) string {
	return visitor.VisitCircle(c)
}

type Rectangle struct {
	Width  float64
	Height float64
}

func (r Rectangle) Accept(visitor Visitor) string {
	return visitor.VisitRectangle(r)
}

type AreaVisitor struct{}

func (AreaVisitor) VisitCircle(circle Circle) string {
	return "calculate circle area"
}

func (AreaVisitor) VisitRectangle(rectangle Rectangle) string {
	return "calculate rectangle area"
}

type DrawVisitor struct{}

func (DrawVisitor) VisitCircle(circle Circle) string {
	return "draw circle"
}

func (DrawVisitor) VisitRectangle(rectangle Rectangle) string {
	return "draw rectangle"
}

GoF 23 种设计模式清单

严格按照 GoF 的 23 种设计模式,分类如下:

分类 设计模式
创建型 单例、工厂方法、抽象工厂、建造者、原型
结构型 适配器、桥接、组合、装饰器、外观、享元、代理
行为型 责任链、命令、解释器、迭代器、中介者、备忘录、观察者、状态、策略、模板方法、访问者

简单工厂虽然非常常见,但它不是 GoF 23 种之一,可以作为工厂方法的简化版本理解。

posted @ 2026-07-04 00:27  zhangsan213  阅读(2)  评论(0)    收藏  举报