Design Pattern设计模式是对编程面临的相同或相似的问题抽象出的一种通解。总共分为23种 ,3类:创建型6种、结构型7种、行为型11种。
设计模式的优点
- 代码复用和工程化
- 提升代码质量,易扩展,易维护,易理解
- 面试
创建型模式
创建型模式(Creational Patterns)是一类用于处理对象创建的设计模式。控制实例化过程,通过封装对象的创建逻辑,降低系统的耦合度。提升复用性和可维护性。
单例模式
让某些对象在全局上唯一,不会出现多个实例。
可以减少资源浪费 ,占用内存和句柄; 多个实例可能会出现数据不一致;减少资源竞争, 防止高并发场景 下可能耗尽系统资源
应用场景:单例数据库
| 场景 | 说明 |
|---|---|
| 数据库连接池 | 管理数据库连接,避免重复创建连接 |
| 日志记录器 | 统一日志输出,避免多实例冲突 |
| 配置管理 | 全局配置信息,保证配置一致性 |
| 线程池 | 管理线程资源,控制并发数量 |
| 缓存系统 | 共享缓存数据,提高访问效率 |
| 设备驱动 | 控制硬件设备访问 |
| 注册表 | 管理全局注册信息 |
| 应用上下文 | 存储应用全局状态 |
Go
package db
import (
"database/sql"
"fmt"
"sync"
_ "github.com/go-sql-driver/mysql"
)
type DBPool struct {
pool *sql.DB
}
var dbInstance *DBPool
var dbOnce sync.Once
// 获取数据库连接池单例
func GetDBPool() (*DBPool, error) {
var err error
dbOnce.Do(func() {
fmt.Println("正在初始化数据库连接池...")
// 创建数据库连接
dsn := "user:password@tcp(localhost:3306)/dbname"
db, err := sql.Open("mysql", dsn)
if err != nil {
fmt.Printf("数据库连接失败: %v\n", err)
return
}
// 设置连接池参数
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * 60) // 5分钟
// 测试连接
if err = db.Ping(); err != nil {
fmt.Printf("数据库连接测试失败: %v\n", err)
db.Close()
return
}
dbInstance = &DBPool{pool: db}
fmt.Println("数据库连接池初始化成功")
})
if err != nil {
return nil, err
}
return dbInstance, nil
}
sync.Once 保证初始化只执行一次并且线程安全 。延迟初始化,按需创建,不会占用过多系统资源。私有化构造,防止外部创建。提供简单的访问点。
简单工厂模式
将对象的创建过程封装进工厂类,通过参数不同来决定对象的类型。可以隐藏类名,只需知道参数即可。
应用场景
| 应用场景 | 说明 | 示例 |
|---|---|---|
| 日志记录系统 | 根据日志类型创建不同的日志处理器 | 控制台日志、文件日志、数据库日志 |
| 支付系统 | 根据支付方式创建不同的支付处理器 | 支付宝、微信支付、银联支付 |
| 数据库连接 | 根据数据库类型创建不同的连接 | MySQL、PostgreSQL、MongoDB |
| 图形绘制 | 根据图形类型创建不同的绘制器 | 圆形、矩形、三角形 |
| 文件处理 | 根据文件类型创建不同的处理器 | PDF、Excel、Word |
| 缓存系统 | 根据缓存类型创建不同的缓存 | Redis、Memcached、本地缓存 |
| 消息队列 | 根据队列类型创建不同的客户端 | RabbitMQ、Kafka、Redis |
Go
package main
import "fmt"
// ========== 抽象产品接口 ==========
type Payment interface {
Pay(amount float64) bool
Refund(orderID string) bool
GetPaymentMethod() string
}
// ========== 具体产品实现 ==========
// 支付宝支付
type Alipay struct{}
func (a *Alipay) Pay(amount float64) bool {
fmt.Printf("【支付宝】正在支付 %.2f 元...\n", amount)
// 模拟支付逻辑
return true
}
func (a *Alipay) Refund(orderID string) bool {
fmt.Printf("【支付宝】正在退款,订单号: %s\n", orderID)
return true
}
func (a *Alipay) GetPaymentMethod() string {
return "Alipay"
}
// 微信支付
type WechatPay struct{}
func (w *WechatPay) Pay(amount float64) bool {
fmt.Printf("【微信支付】正在支付 %.2f 元...\n", amount)
return true
}
func (w *WechatPay) Refund(orderID string) bool {
fmt.Printf("【微信支付】正在退款,订单号: %s\n", orderID)
return true
}
func (w *WechatPay) GetPaymentMethod() string {
return "WechatPay"
}
// 银联支付
type UnionPay struct{}
func (u *UnionPay) Pay(amount float64) bool {
fmt.Printf("【银联支付】正在支付 %.2f 元...\n", amount)
return true
}
func (u *UnionPay) Refund(orderID string) bool {
fmt.Printf("【银联支付】正在退款,订单号: %s\n", orderID)
return true
}
func (u *UnionPay) GetPaymentMethod() string {
return "UnionPay"
}
// ========== 简单工厂类 ==========
type PaymentFactory struct{}
// 支付方式常量
const (
PAY_ALIPAY = "alipay"
PAY_WECHAT = "wechat"
PAY_UNIONPAY = "unionpay"
)
// 根据支付方式创建对应的支付对象
func (f *PaymentFactory) Create(paymentType string) (Payment, error) {
switch paymentType {
case PAY_ALIPAY:
return &Alipay{}, nil
case PAY_WECHAT:
return &WechatPay{}, nil
case PAY_UNIONPAY:
return &UnionPay{}, nil
default:
return nil, fmt.Errorf("不支持的支付方式: %s", paymentType)
}
}
// ========== 客户端使用 ==========
func main() {
factory := &PaymentFactory{}
// 模拟用户选择不同的支付方式
paymentTypes := []string{PAY_ALIPAY, PAY_WECHAT, PAY_UNIONPAY}
amounts := []float64{99.99, 199.50, 299.00}
for i, paymentType := range paymentTypes {
fmt.Printf("\n===== 订单 %d =====\n", i+1)
// 通过工厂创建支付对象
payment, err := factory.Create(paymentType)
if err != nil {
fmt.Printf("创建支付对象失败: %v\n", err)
continue
}
fmt.Printf("支付方式: %s\n", payment.GetPaymentMethod())
// 执行支付
success := payment.Pay(amounts[i])
if success {
fmt.Printf("支付成功!金额: %.2f 元\n", amounts[i])
// 模拟退款
payment.Refund(fmt.Sprintf("ORDER-%06d", i+1))
}
}
}
简单工厂是一个工厂对应了多种产品 factory.create(xxx),简单但不符合开闭原则。
工厂方法模式
工厂方法模式是定义了一个创建对象接口,根据实现接口的子类来决定创建哪一种产品。
与简单工厂的区别是一个工厂只对应一个产品。符合开闭原则,代码多但灵活易扩展。
Go
package main
import "fmt"
// ========== 抽象产品 ==========
type Payment interface {
Pay(amount float64) bool
GetPaymentMethod() string
}
// ========== 具体产品 ==========
type Alipay struct{}
func (a *Alipay) Pay(amount float64) bool {
fmt.Printf("【支付宝】支付 %.2f 元\n", amount)
return true
}
func (a *Alipay) GetPaymentMethod() string { return "Alipay" }
type WechatPay struct{}
func (w *WechatPay) Pay(amount float64) bool {
fmt.Printf("【微信支付】支付 %.2f 元\n", amount)
return true
}
func (w *WechatPay) GetPaymentMethod() string { return "WechatPay" }
type UnionPay struct{}
func (u *UnionPay) Pay(amount float64) bool {
fmt.Printf("【银联支付】支付 %.2f 元\n", amount)
return true
}
func (u *UnionPay) GetPaymentMethod() string { return "UnionPay" }
// ========== 抽象工厂 ==========
type PaymentFactory interface {
CreatePayment() Payment
}
// ========== 具体工厂 ==========
type AlipayFactory struct{}
func (f *AlipayFactory) CreatePayment() Payment {
return &Alipay{}
}
type WechatPayFactory struct{}
func (f *WechatPayFactory) CreatePayment() Payment {
return &WechatPay{}
}
type UnionPayFactory struct{}
func (f *UnionPayFactory) CreatePayment() Payment {
return &UnionPay{}
}
// ========== 客户端使用 ==========
func ProcessPayment(factory PaymentFactory, amount float64) {
payment := factory.CreatePayment()
fmt.Printf("使用 %s 支付\n", payment.GetPaymentMethod())
payment.Pay(amount)
fmt.Println()
}
func main() {
fmt.Println("===== 工厂方法模式示例 =====\n")
// 使用不同的支付工厂
ProcessPayment(&AlipayFactory{}, 100.0)
ProcessPayment(&WechatPayFactory{}, 200.0)
ProcessPayment(&UnionPayFactory{}, 300.0)
}
// 新增支付方式,无需修改现有代码
// 只需添加新的工厂类即可
// 示例:新增比特币支付
// type BitcoinPay struct{}
// func (b *BitcoinPay) Pay(amount float64) bool { ... }
// func (b *BitcoinPay) GetPaymentMethod() string { return "Bitcoin" }
//
// type BitcoinPayFactory struct{}
// func (f *BitcoinPayFactory) CreatePayment() Payment {
// return &BitcoinPay{}
// }
//
// ProcessPayment(&BitcoinPayFactory{}, 500.0)
适用场景类似于简单工厂,但是如果产品类别较少不太适用,抽象过多,过于繁琐。
适合产品种类多且经常变化。系统需要灵活拓展的场景。
抽象工厂模式
创建一系列相互依赖对象的接口,而无指定它们具体的类。
一个工厂能产生多个不同类型 但是属于同"系列/风格"的产品。客户端只需要依赖接口的抽象而无需关心具体实现。
Go
package main
import "fmt"
// ========== 抽象产品:按钮 ==========
type Button interface {
Render() string
Click() string
}
// ========== 具体产品:Windows按钮 ==========
type WindowsButton struct{}
func (w *WindowsButton) Render() string {
return "[Windows Button]"
}
func (w *WindowsButton) Click() string {
return "Windows button clicked"
}
// ========== 具体产品:MacOS按钮 ==========
type MacOSButton struct{}
func (m *MacOSButton) Render() string {
return "[MacOS Button]"
}
func (m *MacOSButton) Click() string {
return "MacOS button clicked"
}
// ========== 抽象产品:复选框 ==========
type Checkbox interface {
Render() string
Check() string
}
// ========== 具体产品:Windows复选框 ==========
type WindowsCheckbox struct{}
func (w *WindowsCheckbox) Render() string {
return "[Windows Checkbox]"
}
func (w *WindowsCheckbox) Check() string {
return "Windows checkbox checked"
}
// ========== 具体产品:MacOS复选框 ==========
type MacOSCheckbox struct{}
func (m *MacOSCheckbox) Render() string {
return "[MacOS Checkbox]"
}
func (m *MacOSCheckbox) Check() string {
return "MacOS checkbox checked"
}
// ========== 抽象工厂 ==========
type GUIFactory interface {
CreateButton() Button
CreateCheckbox() Checkbox
}
// ========== 具体工厂:Windows工厂 ==========
type WindowsFactory struct{}
func (f *WindowsFactory) CreateButton() Button {
return &WindowsButton{}
}
func (f *WindowsFactory) CreateCheckbox() Checkbox {
return &WindowsCheckbox{}
}
// ========== 具体工厂:MacOS工厂 ==========
type MacOSFactory struct{}
func (f *MacOSFactory) CreateButton() Button {
return &MacOSButton{}
}
func (f *MacOSFactory) CreateCheckbox() Checkbox {
return &MacOSCheckbox{}
}
// ========== 客户端代码 ==========
func RenderUI(factory GUIFactory) {
button := factory.CreateButton()
checkbox := factory.CreateCheckbox()
fmt.Println("渲染界面:")
fmt.Println(" 按钮:", button.Render())
fmt.Println(" 复选框:", checkbox.Render())
fmt.Println("\n用户交互:")
fmt.Println(" ", button.Click())
fmt.Println(" ", checkbox.Check())
}
func main() {
fmt.Println("===== Windows 风格界面 =====")
windowsFactory := &WindowsFactory{}
RenderUI(windowsFactory)
fmt.Println("\n===== MacOS 风格界面 =====")
macFactory := &MacOSFactory{}
RenderUI(macFactory)
}
特点是复杂度较高,一个工厂能产生产品族,扩展产品族简单,扩展产品困难。
建造者模式
将一个复杂对象的构建和表示分离,同样的构建过程可以创建不同的表示。
特点是将复杂对象的构建分解为多个步骤 。可以控制对象创建阶段。
| 角色 | 说明 |
|---|---|
| Product(产品) | 要创建的复杂对象,包含多个组成部分 |
| Builder(抽象建造者) | 定义构建产品各部分的抽象接口 |
| ConcreteBuilder(具体建造者) | 实现Builder接口,构造并装配产品的各个部分 |
| Director(指挥者) | 负责协调建造者的构建步骤,指导构建过程 |
Go
package main
import "fmt"
// ========== 产品:房屋 ==========
type House struct {
Foundation string // 地基
Structure string // 框架
Roof string // 屋顶
Interior string // 内部装修
Rooms int // 房间数量
}
func (h *House) Display() {
fmt.Println("===== 房屋信息 =====")
fmt.Printf("地基: %s\n", h.Foundation)
fmt.Printf("框架: %s\n", h.Structure)
fmt.Printf("屋顶: %s\n", h.Roof)
fmt.Printf("内部装修: %s\n", h.Interior)
fmt.Printf("房间数量: %d\n", h.Rooms)
fmt.Println("====================")
}
// ========== 抽象建造者 ==========
type HouseBuilder interface {
BuildFoundation()
BuildStructure()
BuildRoof()
BuildInterior()
SetRooms(int)
GetHouse() *House
}
// ========== 具体建造者1:普通房屋建造者 ==========
type SimpleHouseBuilder struct {
house *House
}
func NewSimpleHouseBuilder() *SimpleHouseBuilder {
return &SimpleHouseBuilder{
house: &House{},
}
}
func (b *SimpleHouseBuilder) BuildFoundation() {
b.house.Foundation = "混凝土地基"
fmt.Println(" [建造] 混凝土地基")
}
func (b *SimpleHouseBuilder) BuildStructure() {
b.house.Structure = "砖混结构"
fmt.Println(" [建造] 砖混结构")
}
func (b *SimpleHouseBuilder) BuildRoof() {
b.house.Roof = "平屋顶"
fmt.Println(" [建造] 平屋顶")
}
func (b *SimpleHouseBuilder) BuildInterior() {
b.house.Interior = "简装修"
fmt.Println(" [建造] 简装修")
}
func (b *SimpleHouseBuilder) SetRooms(num int) {
b.house.Rooms = num
fmt.Printf(" [设置] %d 个房间\n", num)
}
func (b *SimpleHouseBuilder) GetHouse() *House {
return b.house
}
// ========== 具体建造者2:豪华别墅建造者 ==========
type LuxuryVillaBuilder struct {
house *House
}
func NewLuxuryVillaBuilder() *LuxuryVillaBuilder {
return &LuxuryVillaBuilder{
house: &House{},
}
}
func (b *LuxuryVillaBuilder) BuildFoundation() {
b.house.Foundation = "钢筋混凝土深基础"
fmt.Println(" [建造] 钢筋混凝土深基础")
}
func (b *LuxuryVillaBuilder) BuildStructure() {
b.house.Structure = "钢结构+玻璃幕墙"
fmt.Println(" [建造] 钢结构+玻璃幕墙")
}
func (b *LuxuryVillaBuilder) BuildRoof() {
b.house.Roof = "坡屋顶+太阳能板"
fmt.Println(" [建造] 坡屋顶+太阳能板")
}
func (b *LuxuryVillaBuilder) BuildInterior() {
b.house.Interior = "豪华精装"
fmt.Println(" [建造] 豪华精装")
}
func (b *LuxuryVillaBuilder) SetRooms(num int) {
b.house.Rooms = num
fmt.Printf(" [设置] %d 个房间(含主卧、客卧、书房)\n", num)
}
func (b *LuxuryVillaBuilder) GetHouse() *House {
return b.house
}
// ========== 指挥者 ==========
type Director struct {
builder HouseBuilder
}
func NewDirector(builder HouseBuilder) *Director {
return &Director{builder: builder}
}
func (d *Director) SetBuilder(builder HouseBuilder) {
d.builder = builder
}
// 标准建造流程
func (d *Director) ConstructHouse() *House {
fmt.Println("\n【开始建造】")
d.builder.BuildFoundation()
d.builder.BuildStructure()
d.builder.BuildRoof()
d.builder.BuildInterior()
d.builder.SetRooms(3)
fmt.Println("【建造完成】\n")
return d.builder.GetHouse()
}
// 快速建造流程(简化版)
func (d *Director) ConstructQuickHouse() *House {
fmt.Println("\n【快速建造】")
d.builder.BuildFoundation()
d.builder.BuildStructure()
d.builder.SetRooms(2)
fmt.Println("【快速建造完成】\n")
return d.builder.GetHouse()
}
func main() {
fmt.Println("===== 建造者模式示例:房屋建造 =====")
// 方式1:使用指挥者协调建造过程
fmt.Println("\n【方式1:使用指挥者】")
// 建造普通房屋
simpleBuilder := NewSimpleHouseBuilder()
director := NewDirector(simpleBuilder)
simpleHouse := director.ConstructHouse()
simpleHouse.Display()
// 建造豪华别墅
luxuryBuilder := NewLuxuryVillaBuilder()
director.SetBuilder(luxuryBuilder)
luxuryHouse := director.ConstructHouse()
luxuryHouse.Display()
// 方式2:直接使用建造者(不使用指挥者)
fmt.Println("\n【方式2:直接使用建造者】")
customBuilder := NewSimpleHouseBuilder()
customBuilder.BuildFoundation()
customBuilder.BuildStructure()
customBuilder.SetRooms(4) // 自定义房间数量
customBuilder.BuildRoof()
customBuilder.BuildInterior()
customHouse := customBuilder.GetHouse()
customHouse.Display()
// 方式3:使用指挥者的不同建造流程
fmt.Println("\n【方式3:使用不同的建造流程】")
quickBuilder := NewSimpleHouseBuilder()
director.SetBuilder(quickBuilder)
quickHouse := director.ConstructQuickHouse()
quickHouse.Display()
}
原型模式
通过复制现有对象来创建新对象,而不是通过新建类的方式,避免了某些对象重复初始化。
但会引入一个深浅拷贝的问题。
深浅拷贝
| 特性 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 基本类型 | 复制值 | 复制值 |
| 引用类型 | 复制引用地址 | 递归复制对象 |
| 内存共享 | 是 | 否 |
| 修改影响 | 会相互影响 | 独立 |
| 实现复杂度 | 低 | 高 |
| 性能 | 高 | 低 |
Go
package main
import "fmt"
// ========== 浅拷贝示例 ==========
type Address struct {
Street string
City string
}
type Person struct {
Name string
Age int
Address *Address // 引用类型
}
// 浅拷贝:只复制顶层结构
func (p *Person) ShallowClone() *Person {
return &Person{
Name: p.Name,
Age: p.Age,
Address: p.Address, // 只复制指针,不复制对象
}
}
// ========== 深拷贝示例 ==========
func (p *Person) DeepClone() *Person {
return &Person{
Name: p.Name,
Age: p.Age,
Address: &Address{ // 递归复制对象
Street: p.Address.Street,
City: p.Address.City,
},
}
}
Go
package main
import (
"fmt"
"encoding/json"
)
// ========== 简历结构 ==========
type Resume struct {
Name string
Age int
Gender string
WorkExperience []WorkExp
Skills []string
}
type WorkExp struct {
Company string
Position string
Years int
}
// ========== 克隆接口 ==========
type Cloneable interface {
Clone() Cloneable
}
// ========== 浅克隆实现 ==========
func (r *Resume) ShallowClone() *Resume {
return &Resume{
Name: r.Name,
Age: r.Age,
Gender: r.Gender,
WorkExperience: r.WorkExperience, // 浅拷贝切片
Skills: r.Skills, // 浅拷贝切片
}
}
// ========== 深克隆实现(使用JSON序列化) ==========
func (r *Resume) DeepClone() *Resume {
// 序列化为JSON
data, _ := json.Marshal(r)
// 反序列化为新对象
var newResume Resume
json.Unmarshal(data, &newResume)
return &newResume
}
// ========== 深克隆实现(手动递归) ==========
func (r *Resume) DeepCloneManual() *Resume {
// 复制工作经历
workExps := make([]WorkExp, len(r.WorkExperience))
for i, exp := range r.WorkExperience {
workExps[i] = WorkExp{
Company: exp.Company,
Position: exp.Position,
Years: exp.Years,
}
}
// 复制技能
skills := make([]string, len(r.Skills))
copy(skills, r.Skills)
return &Resume{
Name: r.Name,
Age: r.Age,
Gender: r.Gender,
WorkExperience: workExps,
Skills: skills,
}
}
适用于:对象创建成本高,需要大量的相似对象且需要动态配置对象,实现撤销操作。
不适合适用:当对象简单、创建成本低、对象类型常常变化。
结构型模式
结构型模式关注将类和对象组合 成更大的结构,在不改变对象的情况下实现新的功能或者优化结构。
结构型对象的核心思想是组合而非继承来复用和拓展代码。
代理模式
代理模式为其他对象提供占位符,来控制对对象的访问。
引入了中间层,可以解耦核心逻辑于其余关注点 。且增加了控制访问。并且在不修改原对象的前提下增加新功能。
Go
package main
import (
"fmt"
"time"
)
// ========== 图片接口 ==========
type Image interface {
Display()
}
// ========== 真实图片 ==========
type RealImage struct {
filename string
}
func NewRealImage(filename string) *RealImage {
fmt.Printf("加载图片: %s\n", filename)
time.Sleep(2 * time.Second) // 模拟耗时加载
return &RealImage{filename: filename}
}
func (r *RealImage) Display() {
fmt.Printf("显示图片: %s [已加载]\n", r.filename)
}
// ========== 虚拟代理 ==========
type ImageProxy struct {
filename string
realImage *RealImage
loaded bool
}
func NewImageProxy(filename string) *ImageProxy {
return &ImageProxy{
filename: filename,
loaded: false,
}
}
func (p *ImageProxy) Display() {
if !p.loaded {
fmt.Printf("延迟加载图片: %s\n", p.filename)
p.realImage = NewRealImage(p.filename)
p.loaded = true
}
p.realImage.Display()
}
类型:为不同地址空间对象提供本地代理。虚拟代理,根据对象创建大对象。保护代码,控制原始对象的访问权限。
桥接模式
将抽象部分和实现部分进行分离,让它们可以独立进行变化。
将系统拆分为两个独立的变化,对其进行解耦。通过组合关系替代继承,避免类爆炸。抽象层和独立层独立变化互不影响。
Go
package main
import "fmt"
// ========== 实现层接口:渲染器 ==========
type Renderer interface {
RenderCircle(radius float64)
RenderSquare(side float64)
RenderTriangle(base, height float64)
}
// ========== 具体实现1:SVG渲染器 ==========
type SVGRenderer struct{}
func (r *SVGRenderer) RenderCircle(radius float64) {
fmt.Printf(" [SVG] 绘制圆形,半径: %.2f\n", radius)
}
func (r *SVGRenderer) RenderSquare(side float64) {
fmt.Printf(" [SVG] 绘制正方形,边长: %.2f\n", side)
}
func (r *SVGRenderer) RenderTriangle(base, height float64) {
fmt.Printf(" [SVG] 绘制三角形,底: %.2f, 高: %.2f\n", base, height)
}
// ========== 具体实现2:Canvas渲染器 ==========
type CanvasRenderer struct{}
func (r *CanvasRenderer) RenderCircle(radius float64) {
fmt.Printf(" [Canvas] 绘制圆形,半径: %.2f\n", radius)
}
func (r *CanvasRenderer) RenderSquare(side float64) {
fmt.Printf(" [Canvas] 绘制正方形,边长: %.2f\n", side)
}
func (r *CanvasRenderer) RenderTriangle(base, height float64) {
fmt.Printf(" [Canvas] 绘制三角形,底: %.2f, 高: %.2f\n", base, height)
}
// ========== 抽象层:形状 ==========
type Shape interface {
Draw()
}
// ========== 具体抽象:圆形 ==========
type Circle struct {
renderer Renderer
radius float64
}
func NewCircle(renderer Renderer, radius float64) *Circle {
return &Circle{
renderer: renderer,
radius: radius,
}
}
func (c *Circle) Draw() {
fmt.Println("绘制圆形:")
c.renderer.RenderCircle(c.radius)
}
// ========== 具体抽象:正方形 ==========
type Square struct {
renderer Renderer
side float64
}
func NewSquare(renderer Renderer, side float64) *Square {
return &Square{
renderer: renderer,
side: side,
}
}
func (s *Square) Draw() {
fmt.Println("绘制正方形:")
s.renderer.RenderSquare(s.side)
}
// ========== 具体抽象:三角形 ==========
type Triangle struct {
renderer Renderer
base float64
height float64
}
func NewTriangle(renderer Renderer, base, height float64) *Triangle {
return &Triangle{
renderer: renderer,
base: base,
height: height,
}
}
func (t *Triangle) Draw() {
fmt.Println("绘制三角形:")
t.renderer.RenderTriangle(t.base, t.height)
}
组合模式
组合模式将对象组合成树形结构。可以统一处理单个对象和组合对象。
叶子节点和容器节点实现相同的接口。通过递归的方式处理树形结构。
|---------------------|---------------------------|
| Component(组件接口) | 定义所有对象的公共接口,包括叶子节点和容器节点 |
| Leaf(叶子节点) | 表示树中的叶子对象,没有子节点 |
| Composite(容器节点) | 表示容器对象,包含子组件集合,实现管理子组件的方法 |
Go
package main
import (
"fmt"
"strings"
)
// ========== 组件接口 ==========
type FileSystemComponent interface {
GetName() string
GetSize() int64
Display(indent string)
Add(component FileSystemComponent) error
Remove(component FileSystemComponent) error
Search(name string) FileSystemComponent
}
// ========== 叶子节点:文件 ==========
type File struct {
name string
size int64
}
func NewFile(name string, size int64) *File {
return &File{
name: name,
size: size,
}
}
func (f *File) GetName() string {
return f.name
}
func (f *File) GetSize() int64 {
return f.size
}
func (f *File) Display(indent string) {
fmt.Printf(" %s (%d KB)\n", indent, f.name, f.size)
}
// 叶子节点不支持添加和删除
func (f *File) Add(component FileSystemComponent) error {
return fmt.Errorf("文件不支持添加子组件")
}
func (f *File) Remove(component FileSystemComponent) error {
return fmt.Errorf("文件不支持删除子组件")
}
func (f *File) Search(name string) FileSystemComponent {
if f.name == name {
return f
}
return nil
}
// ========== 容器节点:目录 ==========
type Directory struct {
name string
children []FileSystemComponent
}
func NewDirectory(name string) *Directory {
return &Directory{
name: name,
children: make([]FileSystemComponent, 0),
}
}
func (d *Directory) GetName() string {
return d.name
}
func (d *Directory) GetSize() int64 {
var total int64 = 0
for _, child := range d.children {
total += child.GetSize()
}
return total
}
func (d *Directory) Display(indent string) {
fmt.Printf(" %s (总大小: %d KB)\n", indent, d.name, d.GetSize())
for _, child := range d.children {
child.Display(indent + " ")
}
}
func (d *Directory) Add(component FileSystemComponent) error {
d.children = append(d.children, component)
return nil
}
func (d *Directory) Remove(component FileSystemComponent) error {
for i, child := range d.children {
if child == component {
d.children = append(d.children[:i], d.children[i+1:]...)
return nil
}
}
return fmt.Errorf("未找到要删除的组件")
}
func (d *Directory) Search(name string) FileSystemComponent {
if d.name == name {
return d
}
for _, child := range d.children {
if result := child.Search(name); result != nil {
return result
}
}
return nil
}
// ========== 文件系统管理器 ==========
type FileSystem struct {
root *Directory
}
func NewFileSystem() *FileSystem {
return &FileSystem{
root: NewDirectory("root"),
}
}
func (fs *FileSystem) Add(component FileSystemComponent) {
fs.root.Add(component)
}
func (fs *FileSystem) Display() {
fmt.Println("===== 文件系统结构 =====")
fs.root.Display("")
fmt.Println()
}
func (fs *FileSystem) Search(name string) FileSystemComponent {
return fs.root.Search(name)
}
func (fs *FileSystem) GetTotalSize() int64 {
return fs.root.GetSize()
}
| 场景 | 说明 | 示例 |
|---|---|---|
| 树形结构 | 需要表示部分-整体层次关系 | 文件系统、组织架构 |
| 统一处理 | 需要统一处理单个对象和组合对象 | 菜单系统、图形界面 |
| 递归操作 | 需要递归处理树形结构 | XML解析、DOM操作 |
| 动态构建 | 需要动态构建和修改结构 | 配置系统、UI组件 |
| 层次管理 | 需要管理层次化的对象 | 产品分类、权限系统 |
装饰器模式
动态给对象增加一些额外功能。可以动态扩展,适用组合而非继承来扩展功能。装饰器和被装饰对象使用相同接口。
|------------------------------|------------------------------------|
| Component(组件接口) | 定义对象的公共接口,装饰器和被装饰对象都实现此接口 |
| ConcreteComponent(具体组件) | 实现Component接口的具体类,是被装饰的对象 |
| Decorator(装饰器基类) | 实现Component接口,持有Component引用,负责转发调用 |
| ConcreteDecorator(具体装饰器) | 扩展Component对象的行为,添加额外功能 |
Go
package main
import "fmt"
// ========== 组件接口 ==========
type Beverage interface {
Cost() float64
Description() string
}
// ========== 具体组件:基础咖啡 ==========
type Espresso struct{}
func (e *Espresso) Cost() float64 {
return 15.0
}
func (e *Espresso) Description() string {
return "浓缩咖啡"
}
type HouseBlend struct{}
func (h *HouseBlend) Cost() float64 {
return 10.0
}
func (h *HouseBlend) Description() string {
return "混合咖啡"
}
type DarkRoast struct{}
func (d *DarkRoast) Cost() float64 {
return 12.0
}
func (d *DarkRoast) Description() string {
return "深度烘焙咖啡"
}
// ========== 装饰器基类 ==========
type CondimentDecorator struct {
beverage Beverage
}
func (c *CondimentDecorator) Cost() float64 {
return c.beverage.Cost()
}
func (c *CondimentDecorator) Description() string {
return c.beverage.Description()
}
// ========== 具体装饰器1:牛奶 ==========
type Milk struct {
CondimentDecorator
}
func NewMilk(beverage Beverage) *Milk {
return &Milk{
CondimentDecorator: CondimentDecorator{beverage: beverage},
}
}
func (m *Milk) Cost() float64 {
return m.CondimentDecorator.Cost() + 2.0
}
func (m *Milk) Description() string {
return m.CondimentDecorator.Description() + ", 牛奶"
}
// ========== 具体装饰器2:糖 ==========
type Sugar struct {
CondimentDecorator
}
func NewSugar(beverage Beverage) *Sugar {
return &Sugar{
CondimentDecorator: CondimentDecorator{beverage: beverage},
}
}
func (s *Sugar) Cost() float64 {
return s.CondimentDecorator.Cost() + 1.0
}
func (s *Sugar) Description() string {
return s.CondimentDecorator.Description() + ", 糖"
}
// ========== 具体装饰器3:巧克力 ==========
type Chocolate struct {
CondimentDecorator
}
func NewChocolate(beverage Beverage) *Chocolate {
return &Chocolate{
CondimentDecorator: CondimentDecorator{beverage: beverage},
}
}
func (c *Chocolate) Cost() float64 {
return c.CondimentDecorator.Cost() + 3.0
}
func (c *Chocolate) Description() string {
return c.CondimentDecorator.Description() + ", 巧克力"
}
// ========== 具体装饰器4:奶油 ==========
type Whip struct {
CondimentDecorator
}
func NewWhip(beverage Beverage) *Whip {
return &Whip{
CondimentDecorator: CondimentDecorator{beverage: beverage},
}
}
func (w *Whip) Cost() float64 {
return w.CondimentDecorator.Cost() + 2.5
}
func (w *Whip) Description() string {
return w.CondimentDecorator.Description() + ", 奶油"
}
// ========== 具体装饰器5:香草 ==========
type Vanilla struct {
CondimentDecorator
}
func NewVanilla(beverage Beverage) *Vanilla {
return &Vanilla{
CondimentDecorator: CondimentDecorator{beverage: beverage},
}
}
func (v *Vanilla) Cost() float64 {
return v.CondimentDecorator.Cost() + 1.5
}
func (v *Vanilla) Description() string {
return v.CondimentDecorator.Description() + ", 香草"
}
适配器模式
将一个类的接口转换成客户希望的另一个接口,让原本接口不兼容而能一起工作。
包装现有对象而不修改现有代码,让目标类和适配类解耦合。增加代码复用。
Go
package main
import "fmt"
// ========== 目标接口:支付接口 ==========
type Payment interface {
Pay(amount float64) error
Refund(orderID string) error
GetStatus(orderID string) string
}
// ========== 适配者:支付宝支付(第三方库) ==========
type AlipayClient struct {
appID string
}
func NewAlipayClient(appID string) *AlipayClient {
return &AlipayClient{appID: appID}
}
// 支付宝的原生接口
func (a *AlipayClient) AliPay(money float64) bool {
fmt.Printf("[Alipay] 支付宝支付: ¥%.2f\n", money)
return true
}
func (a *AlipayClient) AliRefund(orderNo string) bool {
fmt.Printf("[Alipay] 支付宝退款: 订单 %s\n", orderNo)
return true
}
func (a *AlipayClient) AliQuery(orderNo string) string {
fmt.Printf("[Alipay] 支付宝查询: 订单 %s\n", orderNo)
return "SUCCESS"
}
// ========== 适配者:微信支付(第三方库) ==========
type WechatPayClient struct {
mchID string
}
func NewWechatPayClient(mchID string) *WechatPayClient {
return &WechatPayClient{mchID: mchID}
}
// 微信支付的原生接口
func (w *WechatPayClient) WxPay(money float64) bool {
fmt.Printf("[Wechat] 微信支付: ¥%.2f\n", money)
return true
}
func (w *WechatPayClient) WxRefund(orderNo string) bool {
fmt.Printf("[Wechat] 微信退款: 订单 %s\n", orderNo)
return true
}
func (w *WechatPayClient) WxQuery(orderNo string) string {
fmt.Printf("[Wechat] 微信查询: 订单 %s\n", orderNo)
return "SUCCESS"
}
// ========== 适配器:支付宝适配器 ==========
type AlipayAdapter struct {
alipay *AlipayClient
}
func NewAlipayAdapter(alipay *AlipayClient) *AlipayAdapter {
return &AlipayAdapter{alipay: alipay}
}
func (a *AlipayAdapter) Pay(amount float64) error {
if a.alipay.AliPay(amount) {
fmt.Printf(" 支付成功!\n")
return nil
}
return fmt.Errorf("支付失败")
}
func (a *AlipayAdapter) Refund(orderID string) error {
if a.alipay.AliRefund(orderID) {
fmt.Printf(" 退款成功!\n")
return nil
}
return fmt.Errorf("退款失败")
}
func (a *AlipayAdapter) GetStatus(orderID string) string {
status := a.alipay.AliQuery(orderID)
fmt.Printf(" 订单状态: %s\n", status)
return status
}
// ========== 适配器:微信支付适配器 ==========
type WechatPayAdapter struct {
wechat *WechatPayClient
}
func NewWechatPayAdapter(wechat *WechatPayClient) *WechatPayAdapter {
return &WechatPayAdapter{wechat: wechat}
}
func (w *WechatPayAdapter) Pay(amount float64) error {
if w.wechat.WxPay(amount) {
fmt.Printf(" 支付成功!\n")
return nil
}
return fmt.Errorf("支付失败")
}
func (w *WechatPayAdapter) Refund(orderID string) error {
if w.wechat.WxRefund(orderID) {
fmt.Printf(" 退款成功!\n")
return nil
}
return fmt.Errorf("退款失败")
}
func (w *WechatPayAdapter) GetStatus(orderID string) string {
status := w.wechat.WxQuery(orderID)
fmt.Printf(" 订单状态: %s\n", status)
return status
}
外观模式
为子系统的一些列接口提供一个统一的高层接口,让子系统更容易使用。
简化接口,为复杂子系统提供一个统一的简化接口,可以隐藏子系统实现细节。降低客户端与系统耦合度。
缺点:限制了调用灵活性,外观类可能过于庞大臃肿。
Go
package main
import "fmt"
// ========== 子系统1:投影仪 ==========
type Projector struct {
name string
}
func NewProjector(name string) *Projector {
return &Projector{name: name}
}
func (p *Projector) On() {
fmt.Printf("[Projector] %s 打开\n", p.name)
}
func (p *Projector) Off() {
fmt.Printf("[Projector] %s 关闭\n", p.name)
}
func (p *Projector) SetInput(input string) {
fmt.Printf("[Projector] %s 设置输入源: %s\n", p.name, input)
}
func (p *Projector) SetWideScreenMode() {
fmt.Printf("[Projector] %s 设置宽屏模式\n", p.name)
}
// ========== 子系统2:屏幕 ==========
type Screen struct {
name string
}
func NewScreen(name string) *Screen {
return &Screen{name: name}
}
func (s *Screen) Down() {
fmt.Printf("[Screen] %s 放下\n", s.name)
}
func (s *Screen) Up() {
fmt.Printf("[Screen] %s 收起\n", s.name)
}
// ========== 子系统3:DVD播放器 ==========
type DVDPlayer struct {
name string
}
func NewDVDPlayer(name string) *DVDPlayer {
return &DVDPlayer{name: name}
}
func (d *DVDPlayer) On() {
fmt.Printf("[DVDPlayer] %s 打开\n", d.name)
}
func (d *DVDPlayer) Off() {
fmt.Printf("[DVDPlayer] %s 关闭\n", d.name)
}
func (d *DVDPlayer) InsertDVD(dvd string) {
fmt.Printf("[DVDPlayer] %s 插入DVD: %s\n", d.name, dvd)
}
func (d *DVDPlayer) Play() {
fmt.Printf("[DVDPlayer] %s 播放中...\n", d.name)
}
func (d *DVDPlayer) Stop() {
fmt.Printf("[DVDPlayer] %s 停止播放\n", d.name)
}
func (d *DVDPlayer) Eject() {
fmt.Printf("[DVDPlayer] %s 弹出DVD\n", d.name)
}
// ========== 子系统4:音响 ==========
type Amplifier struct {
name string
}
func NewAmplifier(name string) *Amplifier {
return &Amplifier{name: name}
}
func (a *Amplifier) On() {
fmt.Printf("[Amplifier] %s 打开\n", a.name)
}
func (a *Amplifier) Off() {
fmt.Printf("[Amplifier] %s 关闭\n", a.name)
}
func (a *Amplifier) SetVolume(level int) {
fmt.Printf("[Amplifier] %s 设置音量: %d\n", a.name, level)
}
func (a *Amplifier) SetSurroundSound() {
fmt.Printf("[Amplifier] %s 启用环绕声\n", a.name)
}
// ========== 子系统5:灯光 ==========
type Lights struct {
name string
}
func NewLights(name string) *Lights {
return &Lights{name: name}
}
func (l *Lights) Dim(level int) {
fmt.Printf("[Lights] %s 调暗到 %d%%\n", l.name, level)
}
func (l *Lights) On() {
fmt.Printf("[Lights] %s 打开\n", l.name)
}
// ========== 外观类:家庭影院外观 ==========
type HomeTheaterFacade struct {
projector *Projector
screen *Screen
dvdPlayer *DVDPlayer
amplifier *Amplifier
lights *Lights
}
func NewHomeTheaterFacade(
projector *Projector,
screen *Screen,
dvdPlayer *DVDPlayer,
amplifier *Amplifier,
lights *Lights,
) *HomeTheaterFacade {
return &HomeTheaterFacade{
projector: projector,
screen: screen,
dvdPlayer: dvdPlayer,
amplifier: amplifier,
lights: lights,
}
}
// 简化接口:观看电影
func (h *HomeTheaterFacade) WatchMovie(movie string) {
fmt.Println("\n===== 准备观看电影:", movie, "=====")
h.lights.Dim(10)
h.screen.Down()
h.projector.On()
h.projector.SetWideScreenMode()
h.amplifier.On()
h.amplifier.SetVolume(5)
h.amplifier.SetSurroundSound()
h.dvdPlayer.On()
h.dvdPlayer.InsertDVD(movie)
h.dvdPlayer.Play()
fmt.Println("电影开始播放!🎬")
}
// 简化接口:结束观看
func (h *HomeTheaterFacade) EndMovie() {
fmt.Println("\n===== 结束观看电影 =====")
h.dvdPlayer.Stop()
h.dvdPlayer.Eject()
h.dvdPlayer.Off()
h.projector.Off()
h.screen.Up()
h.amplifier.Off()
h.lights.On()
fmt.Println("家庭影院已关闭")
}
// 简化接口:听音乐
func (h *HomeTheaterFacade) ListenToMusic() {
fmt.Println("\n===== 准备听音乐 =====")
h.lights.Dim(30)
h.amplifier.On()
h.amplifier.SetVolume(7)
h.amplifier.SetSurroundSound()
fmt.Println("音乐开始播放!🎵")
}
// 简化接口:玩游戏
func (h *HomeTheaterFacade) PlayGame() {
fmt.Println("\n===== 准备玩游戏 =====")
h.lights.On()
h.screen.Down()
h.projector.On()
h.projector.SetInput("HDMI")
h.amplifier.On()
h.amplifier.SetVolume(8)
fmt.Println("游戏开始!🎮")
}
享元模式
运用共享技术支持大量细粒度的对象。
通过共享相同状态管理对象,维护对象池,复用已经创建对象。减少对象创建和销毁的开销。
Go
package main
import (
"fmt"
"sync"
)
// ========== 享元接口 ==========
type BulletFlyweight interface {
Fire(x, y float64, direction float64)
GetDamage() int
}
// ========== 具体享元:子弹类型 ==========
type BulletType struct {
name string // 内部状态:子弹名称
damage int // 内部状态:伤害值
speed float64 // 内部状态:速度
texturePath string // 内部状态:纹理路径
}
func NewBulletType(name string, damage int, speed float64, texturePath string) *BulletType {
return &BulletType{
name: name,
damage: damage,
speed: speed,
texturePath: texturePath,
}
}
func (b *BulletType) Fire(x, y float64, direction float64) {
fmt.Printf("发射 %s: 位置(%.1f, %.1f), 方向: %.1f°, 伤害: %d, 速度: %.1f\n",
b.name, x, y, direction, b.damage, b.speed)
}
func (b *BulletType) GetDamage() int {
return b.damage
}
// ========== 享元工厂 ==========
type BulletFactory struct {
pool map[string]*BulletType
mu sync.RWMutex
}
func NewBulletFactory() *BulletFactory {
return &BulletFactory{
pool: make(map[string]*BulletType),
}
}
func (f *BulletFactory) GetBulletType(name string) *BulletType {
f.mu.RLock()
if bullet, exists := f.pool[name]; exists {
f.mu.RUnlock()
return bullet
}
f.mu.RUnlock()
f.mu.Lock()
defer f.mu.Unlock()
if bullet, exists := f.pool[name]; exists {
return bullet
}
// 根据名称创建不同类型的子弹
var bullet *BulletType
switch name {
case "普通子弹":
bullet = NewBulletType("普通子弹", 10, 500.0, "/textures/bullet_normal.png")
case "穿甲子弹":
bullet = NewBulletType("穿甲子弹", 25, 600.0, "/textures/bullet_armor.png")
case "爆炸子弹":
bullet = NewBulletType("爆炸子弹", 50, 400.0, "/textures/bullet_explosive.png")
case "冰冻子弹":
bullet = NewBulletType("冰冻子弹", 15, 450.0, "/textures/bullet_freeze.png")
default:
bullet = NewBulletType("未知子弹", 5, 300.0, "/textures/bullet_unknown.png")
}
f.pool[name] = bullet
fmt.Printf("创建新子弹类型: %s (伤害: %d, 速度: %.1f)\n", name, bullet.damage, bullet.speed)
return bullet
}
func (f *BulletFactory) GetPoolSize() int {
f.mu.RLock()
defer f.mu.RUnlock()
return len(f.pool)
}
// ========== 子弹管理器 ==========
type BulletManager struct {
factory *BulletFactory
activeBullets []*ActiveBullet
}
type ActiveBullet struct {
bulletType *BulletType
x, y float64
direction float64
isActive bool
}
func NewBulletManager() *BulletManager {
return &BulletManager{
factory: NewBulletFactory(),
activeBullets: make([]*ActiveBullet, 0),
}
}
func (m *BulletManager) FireBullet(bulletType string, x, y float64, direction float64) {
bullet := m.factory.GetBulletType(bulletType)
active := &ActiveBullet{
bulletType: bullet,
x: x,
y: y,
direction: direction,
isActive: true,
}
m.activeBullets = append(m.activeBullets, active)
bullet.Fire(x, y, direction)
}
func (m *BulletManager) Update() {
for _, bullet := range m.activeBullets {
if bullet.isActive {
// 更新子弹位置(简化)
bullet.x += bullet.bulletType.speed * 0.01
// fmt.Printf("子弹移动到: (%.1f, %.1f)\n", bullet.x, bullet.y)
}
}
}
func (m *BulletManager) GetStats() {
fmt.Printf("\n===== 子弹统计 =====\n")
fmt.Printf("活跃子弹数: %d\n", len(m.activeBullets))
fmt.Printf("子弹类型数: %d\n", m.factory.GetPoolSize())
// 统计每种子弹的数量
typeCount := make(map[string]int)
for _, bullet := range m.activeBullets {
typeCount[bullet.bulletType.name]++
}
fmt.Println("子弹类型分布:")
for name, count := range typeCount {
fmt.Printf(" %s: %d 发\n", name, count)
}
}
行为型模式
行为型模式主要用于处理对象之间的交互和责任分配来实现更灵活行为与更好的协作。
责任链模式
将请求发送与接收者解耦,请求会沿着处理链条传递。每个对象只负责自己能处理的部分。
Go
package main
import (
"fmt"
"time"
)
// ========== 请假请求 ==========
type LeaveRequest struct {
EmployeeName string
Days int
Reason string
Approved bool
Approver string
ApprovedAt time.Time
}
// ========== 审批者接口 ==========
type Approver interface {
SetNext(approver Approver)
ProcessRequest(request *LeaveRequest) bool
GetName() string
}
// ========== 基础审批者 ==========
type BaseApprover struct {
name string
next Approver
}
func (a *BaseApprover) SetNext(approver Approver) {
a.next = approver
}
func (a *BaseApprover) ProcessNext(request *LeaveRequest) bool {
if a.next != nil {
return a.next.ProcessRequest(request)
}
return false
}
func (a *BaseApprover) GetName() string {
return a.name
}
// ========== 组长审批 ==========
type TeamLeader struct {
BaseApprover
}
func NewTeamLeader(name string) *TeamLeader {
return &TeamLeader{
BaseApprover: BaseApprover{name: name},
}
}
func (t *TeamLeader) ProcessRequest(request *LeaveRequest) bool {
fmt.Printf("\n[组长 %s] 审批请求...\n", t.name)
fmt.Printf(" 员工: %s, 请假天数: %d天, 原因: %s\n",
request.EmployeeName, request.Days, request.Reason)
if request.Days <= 1 {
fmt.Printf(" ✓ 批准: 1天以内组长可直接审批\n")
request.Approved = true
request.Approver = t.name
request.ApprovedAt = time.Now()
return true
}
fmt.Printf(" → 天数超过1天,转交部门经理审批\n")
return t.ProcessNext(request)
}
// ========== 部门经理审批 ==========
type DepartmentManager struct {
BaseApprover
}
func NewDepartmentManager(name string) *DepartmentManager {
return &DepartmentManager{
BaseApprover: BaseApprover{name: name},
}
}
func (d *DepartmentManager) ProcessRequest(request *LeaveRequest) bool {
fmt.Printf("\n[部门经理 %s] 审批请求...\n", d.name)
fmt.Printf(" 员工: %s, 请假天数: %d天, 原因: %s\n",
request.EmployeeName, request.Days, request.Reason)
if request.Days <= 3 {
fmt.Printf(" ✓ 批准: 3天以内部门经理可直接审批\n")
request.Approved = true
request.Approver = d.name
request.ApprovedAt = time.Now()
return true
}
fmt.Printf(" → 天数超过3天,转交总经理审批\n")
return d.ProcessNext(request)
}
// ========== 总经理审批 ==========
type GeneralManager struct {
BaseApprover
}
func NewGeneralManager(name string) *GeneralManager {
return &GeneralManager{
BaseApprover: BaseApprover{name: name},
}
}
func (g *GeneralManager) ProcessRequest(request *LeaveRequest) bool {
fmt.Printf("\n[总经理 %s] 审批请求...\n", g.name)
fmt.Printf(" 员工: %s, 请假天数: %d天, 原因: %s\n",
request.EmployeeName, request.Days, request.Reason)
if request.Days <= 7 {
fmt.Printf(" ✓ 批准: 7天以内总经理可直接审批\n")
request.Approved = true
request.Approver = g.name
request.ApprovedAt = time.Now()
return true
}
fmt.Printf(" ✗ 拒绝: 请假天数超过7天,不予批准\n")
request.Approved = false
return false
}
// ========== 请假审批服务 ==========
type LeaveApprovalService struct {
approver Approver
}
func NewLeaveApprovalService() *LeaveApprovalService {
// 构建审批责任链
teamLeader := NewTeamLeader("张三")
deptManager := NewDepartmentManager("李四")
generalManager := NewGeneralManager("王五")
// 设置链式关系
teamLeader.SetNext(deptManager)
deptManager.SetNext(generalManager)
return &LeaveApprovalService{
approver: teamLeader,
}
}
func (s *LeaveApprovalService) SubmitLeaveRequest(request *LeaveRequest) bool {
fmt.Printf("===== 请假审批流程 =====\n")
fmt.Printf("提交人: %s, 天数: %d天, 原因: %s\n\n",
request.EmployeeName, request.Days, request.Reason)
// 开始审批流程
approved := s.approver.ProcessRequest(request)
// 输出结果
fmt.Println("\n===== 审批结果 =====")
if approved {
fmt.Printf("✅ 审批通过!\n")
fmt.Printf("审批人: %s, 审批时间: %s\n",
request.Approver, request.ApprovedAt.Format("2006-01-02 15:04:05"))
} else {
fmt.Printf("❌ 审批未通过!\n")
}
return approved
}
func main() {
fmt.Println("===== 责任链模式示例:请假审批流程 =====\n")
service := NewLeaveApprovalService()
// 场景1:1天请假 - 组长审批
fmt.Println("【场景1:请1天假】")
request1 := &LeaveRequest{
EmployeeName: "小明",
Days: 1,
Reason: "身体不适",
}
service.SubmitLeaveRequest(request1)
// 场景2:2天请假 - 部门经理审批
fmt.Println("\n【场景2:请2天假】")
request2 := &LeaveRequest{
EmployeeName: "小红",
Days: 2,
Reason: "家中有事",
}
service.SubmitLeaveRequest(request2)
// 场景3:5天请假 - 总经理审批
fmt.Println("\n【场景3:请5天假】")
request3 := &LeaveRequest{
EmployeeName: "小刚",
Days: 5,
Reason: "结婚",
}
service.SubmitLeaveRequest(request3)
// 场景4:10天请假 - 被拒绝
fmt.Println("\n【场景4:请10天假】")
request4 := &LeaveRequest{
EmployeeName: "小芳",
Days: 10,
Reason: "旅游",
}
service.SubmitLeaveRequest(request4)
// 场景5:3天请假 - 部门经理审批
fmt.Println("\n【场景5:请3天假】")
request5 := &LeaveRequest{
EmployeeName: "小李",
Days: 3,
Reason: "照顾家人",
}
service.SubmitLeaveRequest(request5)
}
命令模式
将一个请求封装成对象,从而使你可以用不同的请求对客户进行参数化。对请求排队或记录日志。
Go
package main
import (
"fmt"
"time"
)
// ========== 命令接口 ==========
type Command interface {
Execute()
GetName() string
}
// ========== 接收者:数据库 ==========
type Database struct {
name string
}
func NewDatabase(name string) *Database {
return &Database{name: name}
}
func (db *Database) Connect() {
fmt.Printf("🔌 连接数据库: %s\n", db.name)
time.Sleep(100 * time.Millisecond)
}
func (db *Database) Disconnect() {
fmt.Printf("🔌 断开数据库连接: %s\n", db.name)
time.Sleep(100 * time.Millisecond)
}
func (db *Database) ExecuteQuery(query string) {
fmt.Printf("🔍 执行查询 [%s]: %s\n", db.name, query)
time.Sleep(200 * time.Millisecond)
}
func (db *Database) Backup() {
fmt.Printf("💾 备份数据库: %s\n", db.name)
time.Sleep(300 * time.Millisecond)
}
// ========== 具体命令 ==========
type ConnectCommand struct {
db *Database
}
func NewConnectCommand(db *Database) *ConnectCommand {
return &ConnectCommand{db: db}
}
func (c *ConnectCommand) Execute() {
c.db.Connect()
}
func (c *ConnectCommand) GetName() string {
return "连接数据库"
}
type DisconnectCommand struct {
db *Database
}
func NewDisconnectCommand(db *Database) *DisconnectCommand {
return &DisconnectCommand{db: db}
}
func (c *DisconnectCommand) Execute() {
c.db.Disconnect()
}
func (c *DisconnectCommand) GetName() string {
return "断开连接"
}
type QueryCommand struct {
db *Database
query string
}
func NewQueryCommand(db *Database, query string) *QueryCommand {
return &QueryCommand{db: db, query: query}
}
func (c *QueryCommand) Execute() {
c.db.ExecuteQuery(c.query)
}
func (c *QueryCommand) GetName() string {
return fmt.Sprintf("执行查询: %s", c.query[:20])
}
type BackupCommand struct {
db *Database
}
func NewBackupCommand(db *Database) *BackupCommand {
return &BackupCommand{db: db}
}
func (c *BackupCommand) Execute() {
c.db.Backup()
}
func (c *BackupCommand) GetName() string {
return "备份数据库"
}
// ========== 宏命令(组合多个命令) ==========
type MacroCommand struct {
name string
commands []Command
}
func NewMacroCommand(name string) *MacroCommand {
return &MacroCommand{
name: name,
commands: make([]Command, 0),
}
}
func (mc *MacroCommand) Add(command Command) {
mc.commands = append(mc.commands, command)
}
func (mc *MacroCommand) Execute() {
fmt.Printf("\n🎬 执行宏命令: %s (包含 %d 个子命令)\n", mc.name, len(mc.commands))
for i, cmd := range mc.commands {
fmt.Printf(" [%d/%d] %s\n", i+1, len(mc.commands), cmd.GetName())
cmd.Execute()
}
fmt.Printf("🎬 宏命令执行完成: %s\n", mc.name)
}
func (mc *MacroCommand) GetName() string {
return fmt.Sprintf("宏命令: %s", mc.name)
}
// ========== 命令队列 ==========
type CommandQueue struct {
queue []Command
}
func NewCommandQueue() *CommandQueue {
return &CommandQueue{
queue: make([]Command, 0),
}
}
func (cq *CommandQueue) AddCommand(command Command) {
cq.queue = append(cq.queue, command)
fmt.Printf("✅ 添加命令到队列: %s (队列大小: %d)\n", command.GetName(), len(cq.queue))
}
func (cq *CommandQueue) ExecuteAll() {
fmt.Printf("\n🚀 执行命令队列 (共 %d 个命令)...\n", len(cq.queue))
startTime := time.Now()
for i, cmd := range cq.queue {
fmt.Printf("\n[%d/%d] 执行: %s\n", i+1, len(cq.queue), cmd.GetName())
cmd.Execute()
}
duration := time.Since(startTime)
fmt.Printf("\n✅ 命令队列执行完成,耗时: %.2fs\n", duration.Seconds())
cq.queue = make([]Command, 0)
}
func (cq *CommandQueue) Clear() {
fmt.Printf("🧹 清空命令队列 (原大小: %d)\n", len(cq.queue))
cq.queue = make([]Command, 0)
}
func (cq *CommandQueue) Size() int {
return len(cq.queue)
}
func main() {
fmt.Println("===== 命令模式示例:命令队列和宏命令 =====\n")
// 创建接收者
mainDB := NewDatabase("主数据库")
backupDB := NewDatabase("备份数据库")
// 创建命令队列
queue := NewCommandQueue()
// 场景1:添加单个命令到队列
fmt.Println("【场景1:添加单个命令到队列】")
queue.AddCommand(NewConnectCommand(mainDB))
queue.AddCommand(NewQueryCommand(mainDB, "SELECT * FROM users WHERE active = 1"))
queue.AddCommand(NewBackupCommand(mainDB))
queue.AddCommand(NewDisconnectCommand(mainDB))
fmt.Printf("\n当前队列大小: %d\n", queue.Size())
// 场景2:执行命令队列
fmt.Println("\n【场景2:执行命令队列】")
queue.ExecuteAll()
// 场景3:创建宏命令
fmt.Println("\n【场景3:创建宏命令】")
// 宏命令1:数据库备份流程
backupMacro := NewMacroCommand("数据库备份流程")
backupMacro.Add(NewConnectCommand(backupDB))
backupMacro.Add(NewBackupCommand(backupDB))
backupMacro.Add(NewDisconnectCommand(backupDB))
// 宏命令2:数据迁移流程
migrateMacro := NewMacroCommand("数据迁移流程")
migrateMacro.Add(NewConnectCommand(mainDB))
migrateMacro.Add(NewQueryCommand(mainDB, "SELECT * FROM orders WHERE status = 'pending'"))
migrateMacro.Add(NewConnectCommand(backupDB))
migrateMacro.Add(NewQueryCommand(backupDB, "INSERT INTO orders ..."))
migrateMacro.Add(NewDisconnectCommand(mainDB))
migrateMacro.Add(NewDisconnectCommand(backupDB))
// 将宏命令添加到队列
queue.AddCommand(backupMacro)
queue.AddCommand(migrateMacro)
fmt.Printf("\n当前队列大小: %d (包含宏命令)\n", queue.Size())
// 场景4:执行包含宏命令的队列
fmt.Println("\n【场景4:执行包含宏命令的队列】")
queue.ExecuteAll()
// 场景5:清空队列
fmt.Println("\n【场景5:清空队列】")
queue.AddCommand(NewConnectCommand(mainDB))
queue.AddCommand(NewQueryCommand(mainDB, "SELECT COUNT(*) FROM users"))
queue.Clear()
fmt.Println("\n===== 演示结束 =====")
}
迭代器模式
Go
package main
import "fmt"
// ========== 迭代器接口 ==========
type Iterator interface {
HasNext() bool
Next() interface{}
}
// ========== 聚合接口 ==========
type Aggregate interface {
CreateIterator() Iterator
}
// ========== 具体聚合:书架 ==========
type Bookshelf struct {
books []string
}
func NewBookshelf() *Bookshelf {
return &Bookshelf{
books: make([]string, 0),
}
}
func (b *Bookshelf) AddBook(book string) {
b.books = append(b.books, book)
}
func (b *Bookshelf) GetBookAt(index int) string {
return b.books[index]
}
func (b *Bookshelf) GetSize() int {
return len(b.books)
}
func (b *Bookshelf) CreateIterator() Iterator {
return &BookshelfIterator{
bookshelf: b,
index: 0,
}
}
// ========== 具体迭代器:书架迭代器 ==========
type BookshelfIterator struct {
bookshelf *Bookshelf
index int
}
func (i *BookshelfIterator) HasNext() bool {
return i.index < i.bookshelf.GetSize()
}
func (i *BookshelfIterator) Next() interface{} {
if i.HasNext() {
book := i.bookshelf.GetBookAt(i.index)
i.index++
return book
}
return nil
}
// ========== 反向迭代器 ==========
type ReverseBookshelfIterator struct {
bookshelf *Bookshelf
index int
}
func NewReverseBookshelfIterator(bookshelf *Bookshelf) *ReverseBookshelfIterator {
return &ReverseBookshelfIterator{
bookshelf: bookshelf,
index: bookshelf.GetSize() - 1,
}
}
func (i *ReverseBookshelfIterator) HasNext() bool {
return i.index >= 0
}
func (i *ReverseBookshelfIterator) Next() interface{} {
if i.HasNext() {
book := i.bookshelf.GetBookAt(i.index)
i.index--
return book
}
return nil
}
中介者模式
定义中介对象封装一系列对象之间的交互,让个对象对需要相互引用,进行逻辑解耦。
将对象之间的交互逻辑封装进中介。
对象不会再互相引用而是通过中介者通信。
中介统一协调对象之间的通信。
Go
package main
import (
"fmt"
"time"
)
// ========== 中介者接口 ==========
type ChatRoomMediator interface {
SendMessage(message string, sender User)
RegisterUser(user User)
UnregisterUser(user User)
}
// ========== 同事类接口 ==========
type User interface {
GetName() string
SendMessage(message string)
ReceiveMessage(message string, sender User)
}
// ========== 具体中介者:聊天室 ==========
type ChatRoom struct {
users map[string]User
}
func NewChatRoom() *ChatRoom {
return &ChatRoom{
users: make(map[string]User),
}
}
func (c *ChatRoom) RegisterUser(user User) {
c.users[user.GetName()] = user
fmt.Printf("✅ [%s] 加入聊天室 (当前用户数: %d)\n",
user.GetName(), len(c.users))
}
func (c *ChatRoom) UnregisterUser(user User) {
delete(c.users, user.GetName())
fmt.Printf("👋 [%s] 离开聊天室 (当前用户数: %d)\n",
user.GetName(), len(c.users))
}
func (c *ChatRoom) SendMessage(message string, sender User) {
fmt.Printf("\n📨 [%s] 发送消息: %s\n", sender.GetName(), message)
// 将消息发送给除发送者外的所有用户
for _, user := range c.users {
if user.GetName() != sender.GetName() {
user.ReceiveMessage(message, sender)
}
}
}
func (c *ChatRoom) BroadcastSystemMessage(message string) {
fmt.Printf("\n📢 系统广播: %s\n", message)
for _, user := range c.users {
user.ReceiveMessage(fmt.Sprintf("[系统] %s", message), nil)
}
}
func (c *ChatRoom) GetUserCount() int {
return len(c.users)
}
// ========== 具体同事类:用户 ==========
type ChatUser struct {
name string
mediator ChatRoomMediator
}
func NewChatUser(name string, mediator ChatRoomMediator) *ChatUser {
user := &ChatUser{
name: name,
mediator: mediator,
}
mediator.RegisterUser(user)
return user
}
func (u *ChatUser) GetName() string {
return u.name
}
func (u *ChatUser) SendMessage(message string) {
u.mediator.SendMessage(message, u)
}
func (u *ChatUser) ReceiveMessage(message string, sender User) {
senderName := "系统"
if sender != nil {
senderName = sender.GetName()
}
fmt.Printf(" 📥 [%s] 收到消息来自 [%s]: %s\n",
u.name, senderName, message)
}
func (u *ChatUser) Leave() {
u.mediator.UnregisterUser(u)
}
备忘录模式
不破坏对象的情况下,**捕捉对象的内部状态,**在需要的时候进行回档。
为对象实现快照,不暴露内部细节。
能够支持对象恢复到历史状态。
| 角色 | 说明 | 职责 |
|---|---|---|
| Originator(发起人/原发器) | 拥有内部状态的对象 | 创建备忘录、从备忘录恢复状态 |
| Memento(备忘录) | 存储发起人内部状态的对象 | 保存和提供状态数据 |
| Caretaker(管理者/负责人) | 管理备忘录的对象 | 保存和管理备忘录,但不修改其内容 |
| Client(客户端) | 使用备忘录模式的客户端 | 协调发起人和管理者的操作 |
Go
package main
import (
"fmt"
)
type Node interface {
SetState(str string)
GetState() string
}
type strNode struct {
value string
}
func (s *strNode) SetState(str string) {
s.value = str
}
func (s *strNode) GetState() string {
return s.value
}
type Memento struct {
state string
}
func (m *Memento) GetState() string {
return m.state
}
func (m *Memento) SetState(str string) {
m.state = str
}
type Manager struct {
nodes []Node
}
func (m *Manager) AddNode(node Node) {
m.nodes = append(m.nodes, node)
}
func (m *Manager) GetNode(index int) Node {
return m.nodes[index]
}
func (m *Manager) SaveState() *Memento {
return &Memento{state: m.nodes[0].GetState()}
}
func main() {
manager := &Manager{}
manager.AddNode(&strNode{})
manager.AddNode(&strNode{})
manager.GetNode(0).SetState("hello")
manager.GetNode(1).SetState("world")
fmt.Println(manager.GetNode(0).GetState())
fmt.Println(manager.GetNode(1).GetState())
memento := manager.SaveState()
fmt.Println(memento.GetState())
}
观察者模式
定义了对象间一对多的依赖关系,当对象改变时,依赖它的对象都可以得到通知并自动更新。
解耦了发布和订阅者。可以实现自动通知。
|-----------------------------|-----------------|-------------------|
| Subject(主题/被观察者) | 目标对象,状态变化时通知观察者 | 维护观察者列表,提供注册/注销方法 |
| Observer(观察者) | 依赖于主题的对象 | 定义更新接口,接收主题的通知 |
| ConcreteSubject(具体主题) | 实现主题接口 | 维护自身状态,状态变化时通知观察者 |
| ConcreteObserver(具体观察者) | 实现观察者接口 | 实现更新逻辑,可能需要查询主题状态 |
Go
package main
import "fmt"
type Observer interface {
SetTempture(int)
}
type User struct {
name string
tempture int
}
func (u *User) SetTempture(temp int) {
u.tempture = temp
fmt.Printf("%s 感受的温度为 %d\n", u.name, u.tempture)
}
type WeatherStation struct {
observers []Observer
}
func (w *WeatherStation) Register(observer Observer) {
w.observers = append(w.observers, observer)
}
func (w *WeatherStation) NotifyObservers(temp int) {
for _, observer := range w.observers {
observer.SetTempture(temp)
}
}
func main() {
weatherStation := &WeatherStation{}
user1 := &User{name: "user1"}
user2 := &User{name: "user2"}
weatherStation.Register(user1)
weatherStation.Register(user2)
weatherStation.NotifyObservers(20)
}
状态模式
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
状态封装,由状态驱动行为
| 角色 | 说明 | 职责 |
|---|---|---|
| Context(上下文/环境) | 拥有状态的对象 | 维护当前状态,提供客户端接口 |
| State(状态接口) | 定义状态行为的接口 | 声明所有具体状态的公共方法 |
| ConcreteState(具体状态) | 实现状态接口的类 | 实现特定状态下的行为,可能触发状态转换 |
Go
package main
import "fmt"
type State interface {
Switch(context *Context)
}
type Context struct {
state State
}
func (c *Context) SetState(state State) {
c.state = state
}
func (c *Context) Switch() {
c.state.Switch(c)
}
type OnState struct {
}
type OffState struct {
}
func (o *OnState) Switch(context *Context) {
fmt.Println("关闭")
// 关闭操作
context.SetState(&OffState{})
}
func (o *OffState) Switch(context *Context) {
fmt.Println("开启")
// 开启操作
context.SetState(&OnState{})
}
func main() {
context := &Context{}
context.SetState(&OnState{})
context.Switch()
context.Switch()
context.Switch()
context.Switch()
}
策略模式
定义一系列算法,把它们一个个封装起来,并且使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。
将不同的算法封装为独立个体。可以实现运行时替换,实现算法使用与实现分离。
| 角色 | 说明 | 职责 |
|---|---|---|
| Strategy(策略接口) | 定义所有策略的公共接口 | 声明策略方法 |
| ConcreteStrategy(具体策略) | 实现策略接口的类 | 实现具体的算法 |
| Context(上下文) | 使用策略的对象 | 维护对策略的引用,调用策略方法 |
| Client(客户端) | 使用上下文的客户端 | 选择并设置具体策略 |
Go
package main
import "fmt"
type Pay interface {
pay(int64)
}
type AliPay struct {
}
func (a *AliPay) pay(money int64) {
fmt.Println("支付宝支付 ", money)
}
type WeChatPay struct {
}
func (w *WeChatPay) pay(money int64) {
fmt.Println("微信支付 ", money)
}
type PayStrategy struct {
pay Pay
}
func (p *PayStrategy) Pay(money int64) {
p.pay.pay(money)
}
func (p *PayStrategy) SetPay(pay Pay) {
p.pay = pay
}
func main() {
strategy := &PayStrategy{}
strategy.SetPay(&AliPay{})
strategy.Pay(100)
strategy.SetPay(&WeChatPay{})
strategy.Pay(200)
}
模板方法模式
定义一个操作中的算法骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变算法结构的情况下重新定义该算法的某些特定步骤。
抽象类中固定了算法的整体流程,子类只需要重写特定的步骤。
Go
// ✅ 模板方法模式:定义统一的流程,允许定制细节
// 抽象类(模板)
type Beverage struct{}
// 模板方法 - 定义算法骨架(不可被重写)
func (b *Beverage) PrepareRecipe() {
b.BoilWater() // 固定步骤
b.Brew() // 抽象步骤 - 子类实现
b.PourInCup() // 固定步骤
b.AddCondiments() // 抽象步骤 - 子类实现
}
// 具体步骤 - 可以被重写
func (b *Beverage) BoilWater() {
fmt.Println("烧水...")
}
func (b *Beverage) PourInCup() {
fmt.Println("倒入杯中...")
}
// 抽象方法 - 必须由子类实现
func (b *Beverage) Brew() {
// 子类必须实现
}
func (b *Beverage) AddCondiments() {
// 子类必须实现
}
// 具体子类:咖啡
type Coffee struct {
Beverage
}
func (c *Coffee) Brew() {
fmt.Println("冲泡咖啡...")
}
func (c *Coffee) AddCondiments() {
fmt.Println("添加糖和牛奶...")
}
// 具体子类:茶
type Tea struct {
Beverage
}
func (t *Tea) Brew() {
fmt.Println("浸泡茶包...")
}
func (t *Tea) AddCondiments() {
fmt.Println("添加柠檬...")
}
// 使用
coffee := &Coffee{}
coffee.PrepareRecipe() // 统一流程,不同实现
tea := &Tea{}
tea.PrepareRecipe() // 统一流程,不同实现
访问者模式
允许将算法与对象结构分离。访问者模式的核心思想是 将操作(算法)从对象结构中分离出来,使得可以在不修改对象结构的情况下定义新的操作。
Go
package main
import "fmt"
// Visitor 定义访问者接口
type Visitor interface {
VisitText(text *Text)
VisitImage(image *Image)
VisitTable(table *Table)
}
// Element 定义元素接口
type Element interface {
Accept(visitor Visitor)
}
// Text 是具体元素:文本
type Text struct {
content string
}
func (t *Text) Accept(visitor Visitor) {
visitor.VisitText(t)
}
// Image 是具体元素:图片
type Image struct {
src string
}
func (i *Image) Accept(visitor Visitor) {
visitor.VisitImage(i)
}
// Table 是具体元素:表格
type Table struct {
rows int
cols int
}
func (t *Table) Accept(visitor Visitor) {
visitor.VisitTable(t)
}
// PDFExportVisitor 是具体访问者:导出为 PDF
type PDFExportVisitor struct{}
func (p *PDFExportVisitor) VisitText(text *Text) {
fmt.Printf("Exporting text to PDF: %s\n", text.content)
}
func (p *PDFExportVisitor) VisitImage(image *Image) {
fmt.Printf("Exporting image to PDF: %s\n", image.src)
}
func (p *PDFExportVisitor) VisitTable(table *Table) {
fmt.Printf("Exporting table to PDF: %d rows, %d cols\n", table.rows, table.cols)
}
// HTMLExportVisitor 是具体访问者:导出为 HTML
type HTMLExportVisitor struct{}
func (h *HTMLExportVisitor) VisitText(text *Text) {
fmt.Printf("Exporting text to HTML: %s\n", text.content)
}
func (h *HTMLExportVisitor) VisitImage(image *Image) {
fmt.Printf("Exporting image to HTML: %s\n", image.src)
}
func (h *HTMLExportVisitor) VisitTable(table *Table) {
fmt.Printf("Exporting table to HTML: %d rows, %d cols\n", table.rows, table.cols)
}
// Document 是对象结构
type Document struct {
elements []Element
}
func (d *Document) AddElement(element Element) {
d.elements = append(d.elements, element)
}
func (d *Document) Accept(visitor Visitor) {
for _, element := range d.elements {
element.Accept(visitor)
}
}
func main() {
// 创建文档对象
document := &Document{}
// 添加元素
document.AddElement(&Text{content: "Hello, World!"})
document.AddElement(&Image{src: "image.png"})
document.AddElement(&Table{rows: 3, cols: 2})
// 创建访问者
pdfVisitor := &PDFExportVisitor{}
htmlVisitor := &HTMLExportVisitor{}
// 导出为 PDF
fmt.Println("Exporting to PDF:")
document.Accept(pdfVisitor)
// 导出为 HTML
fmt.Println("\nExporting to HTML:")
document.Accept(htmlVisitor)
}