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 种之一,可以作为工厂方法的简化版本理解。

浙公网安备 33010602011771号