Go语言设计模式:建造者模式详解

文章目录

    • 一、建造者模式概述
      • [1.1 建造者简介](#1.1 建造者简介)
      • [1.2 建造者模式优缺点](#1.2 建造者模式优缺点)
      • [1.3 两种Go实现的对比与选择](#1.3 两种Go实现的对比与选择)
    • 二、案例:实现「手机(Phone)」的建造者模式
      • [1.1 定义产品结构体(Phone)](#1.1 定义产品结构体(Phone))
      • [1.2 定义建造者接口(PhoneBuilder)](#1.2 定义建造者接口(PhoneBuilder))
      • [1.3 实现具体建造者](#1.3 实现具体建造者)
      • [1.4 定义指挥者(Director)](#1.4 定义指挥者(Director))
      • [1.5 客户端调用](#1.5 客户端调用)
      • [1.6 完整代码与执行结果](#1.6 完整代码与执行结果)
    • 三、Go风格建造者模式

一、建造者模式概述

1.1 建造者简介

建造者模式(Builder Pattern) 是一种创建型设计模式,核心是将复杂对象的构建过程与表示分离,使得同样的构建步骤可以生成不同配置的对象。

核心思想:将一个复杂对象的构建过程与它的表示分离。用户只需指定建造的类型,而不需要关心其内部具体的构建细节。

适用场景:当对象包含多个部件、构建步骤固定但具体配置灵活时(如汽车、文档、配置文件等),可通过建造者模式简化创建逻辑,避免代码冗余。

1.2 建造者模式优缺点

优点

  • 分步创建:你可以分步骤创建对象,对构建过程施加更精细的控制。
  • 代码复用:相同的构建代码可以构建出不同的对象表示。
  • 解耦:将产品的构造代码与表示代码分离,使得客户端代码无需知道产品内部的组成细节。
  • 对复杂对象友好:对于包含大量参数和复杂初始化逻辑的对象,建造者模式可以极大地提高代码的可读性和可维护性。

缺点

  • 代码量增加:需要创建多个新的类(Director、Builder、ConcreteBuilder),增加了代码的复杂度。
  • 适用范围有限:如果产品之间的差异性很大,不适合使用建造者模式。它更适用于产品内部结构相似、构建过程稳定的情况。

1.3 两种Go实现的对比与选择

建造者模式的核心价值在于分离复杂对象的构建过程和它的表示

在Go语言中,我们有两种主要的实现方式:

  1. 经典建造者模式:结构严谨,适合构建流程复杂且固定的场景。
  2. 函数式选项模式:Go语言中的惯用模式,通过可变参数和闭包,以更简洁、灵活的方式实现了建造者的核心思想,是处理可选参数和多参数构造问题的首选方案。
特性 经典建造者模式 函数式选项模式
结构 角色分明(Director, Builder, Product),结构更"重"。 结构轻量,主要由 Option 函数和构造函数组成。
灵活性 Director 提供了固定的构建流程,但客户端也可直接使用 Builder,灵活性高。 极其灵活,客户端可以任意组合选项函数。
代码量 较多,需要定义多个接口和结构体。 较少,通常只需定义产品、Option 类型和一系列 WithXxx 函数。
可读性 构建过程被封装在 Director 中,对于复杂流程可能更清晰。 构造函数调用处非常直观,一目了然地看到了所有配置。
Go风格 更偏向于经典的面向对象设计,在Go中略显笨重。 非常符合Go的哲学 ,简洁、优雅、可组合,是Go社区处理多参数构造问题的事实标准
适用场景 当构建过程非常复杂,有严格的、固定的多步骤顺序时,经典模式更合适。 绝大多数场景,特别是当构造函数参数多、有默认值、部分参数可选时。

如何选择?

  • 优先选择函数式选项模式。在99%的Go开发场景中,它都是更优的选择。它完美解决了构造函数参数过多的问题,同时保持了代码的简洁和可扩展性。
  • 只有当你的对象构建逻辑极其复杂 ,包含多个有严格顺序依赖的步骤,并且你希望将这些步骤**封装成一个可复用的"算法"**时,才考虑使用经典的建造者模式。例如,构建一个复杂的SQL查询、一个PDF文档或者一个网络请求的配置流。

二、案例:实现「手机(Phone)」的建造者模式

假设我们需要构建不同配置的手机,包含 品牌、CPU、内存、摄像头、系统 等部件,用户可能需要「入门机」「旗舰机」等不同类型。使用建造者模式可灵活组装这些部件,同时保证构建流程的一致性。

1.1 定义产品结构体(Phone)

首先定义最终要创建的复杂对象------手机,包含基本属性和展示信息的方法。

go 复制代码
package main

import "fmt"

// Phone 产品类:手机
type Phone struct {
	Brand    string // 品牌
	CPU      string // 处理器
	Memory   string // 内存
	Camera   string // 摄像头
	System   string // 系统
	Battery  string // 电池
}

// ShowInfo 展示手机配置
func (p *Phone) ShowInfo() {
	fmt.Printf("手机配置:\n")
	fmt.Printf("品牌:%s\n", p.Brand)
	fmt.Printf("CPU:%s\n", p.CPU)
	fmt.Printf("内存:%s\n", p.Memory)
	fmt.Printf("摄像头:%s\n", p.Camera)
	fmt.Printf("系统:%s\n", p.System)
	fmt.Printf("电池:%s\n", p.Battery)
}

1.2 定义建造者接口(PhoneBuilder)

在 Go 中通过接口定义建造者的「构建步骤」,具体建造者需实现这些方法。

go 复制代码
// PhoneBuilder 建造者接口:定义构建手机的步骤
type PhoneBuilder interface {
	SetBrand()    // 设置品牌
	SetCPU()      // 设置CPU
	SetMemory()   // 设置内存
	SetCamera()   // 设置摄像头
	SetSystem()   // 设置系统
	SetBattery()  // 设置电池
	GetPhone() *Phone // 返回构建好的手机
}

1.3 实现具体建造者

根据不同需求实现具体建造者(如「入门机建造者」「旗舰机建造者」),每个建造者负责具体的部件配置。

go 复制代码
// EntryLevelPhoneBuilder 具体建造者:入门级手机
type EntryLevelPhoneBuilder struct {
	phone *Phone // 持有一个手机对象
}

// 初始化建造者
func NewEntryLevelPhoneBuilder() *EntryLevelPhoneBuilder {
	return &EntryLevelPhoneBuilder{
		phone: &Phone{},
	}
}

func (e *EntryLevelPhoneBuilder) SetBrand() {
	e.phone.Brand = "红米"
}

func (e *EntryLevelPhoneBuilder) SetCPU() {
	e.phone.CPU = "骁龙695"
}

func (e *EntryLevelPhoneBuilder) SetMemory() {
	e.phone.Memory = "6GB + 128GB"
}

func (e *EntryLevelPhoneBuilder) SetCamera() {
	e.phone.Camera = "4800万像素单摄"
}

func (e *EntryLevelPhoneBuilder) SetSystem() {
	e.phone.System = "MIUI 15"
}

func (e *EntryLevelPhoneBuilder) SetBattery() {
	e.phone.Battery = "5000mAh"
}

func (e *EntryLevelPhoneBuilder) GetPhone() *Phone {
	return e.phone
}


// FlagshipPhoneBuilder 具体建造者:旗舰级手机
type FlagshipPhoneBuilder struct {
	phone *Phone
}

func NewFlagshipPhoneBuilder() *FlagshipPhoneBuilder {
	return &FlagshipPhoneBuilder{
		phone: &Phone{},
	}
}

func (f *FlagshipPhoneBuilder) SetBrand() {
	f.phone.Brand = "小米"
}

func (f *FlagshipPhoneBuilder) SetCPU() {
	f.phone.CPU = "骁龙8 Gen3"
}

func (f *FlagshipPhoneBuilder) SetMemory() {
	f.phone.Memory = "12GB + 512GB"
}

func (f *FlagshipPhoneBuilder) SetCamera() {
	f.phone.Camera = "1亿像素三摄(OIS光学防抖)"
}

func (f *FlagshipPhoneBuilder) SetSystem() {
	f.phone.System = "MIUI 15(基于Android 14)"
}

func (f *FlagshipPhoneBuilder) SetBattery() {
	f.phone.Battery = "5500mAh(120W快充)"
}

func (f *FlagshipPhoneBuilder) GetPhone() *Phone {
	return f.phone
}

1.4 定义指挥者(Director)

指挥者负责控制构建流程,按固定步骤调用建造者的方法,确保构建过程的一致性(无需关心具体部件细节)。

go 复制代码
// Director 指挥者:控制构建流程
type Director struct {
	builder PhoneBuilder // 持有一个建造者接口
}

// 初始化指挥者
func NewDirector(builder PhoneBuilder) *Director {
	return &Director{
		builder: builder,
	}
}

// Construct 按固定步骤构建手机
func (d *Director) Construct() {
	d.builder.SetBrand()
	d.builder.SetCPU()
	d.builder.SetMemory()
	d.builder.SetCamera()
	d.builder.SetSystem()
	d.builder.SetBattery()
}

1.5 客户端调用

客户端只需选择具体的建造者,通过指挥者完成构建,无需关心内部细节。

go 复制代码
func main() {
	// 构建入门级手机
	entryBuilder := NewEntryLevelPhoneBuilder()
	entryDirector := NewDirector(entryBuilder)
	entryDirector.Construct() // 执行构建流程
	entryPhone := entryBuilder.GetPhone()
	fmt.Println("=== 入门级手机 ===")
	entryPhone.ShowInfo()

	// 构建旗舰级手机
	flagshipBuilder := NewFlagshipPhoneBuilder()
	flagshipDirector := NewDirector(flagshipBuilder)
	flagshipDirector.Construct()
	flagshipPhone := flagshipBuilder.GetPhone()
	fmt.Println("\n=== 旗舰级手机 ===")
	flagshipPhone.ShowInfo()
}

1.6 完整代码与执行结果

完整代码(builder_pattern.go)

go 复制代码
package main

import "fmt"

// Phone 产品类:手机
type Phone struct {
	Brand   string // 品牌
	CPU     string // 处理器
	Memory  string // 内存
	Camera  string // 摄像头
	System  string // 系统
	Battery string // 电池
}

// ShowInfo 展示手机配置
func (p *Phone) ShowInfo() {
	fmt.Printf("手机配置:\n")
	fmt.Printf("品牌:%s\n", p.Brand)
	fmt.Printf("CPU:%s\n", p.CPU)
	fmt.Printf("内存:%s\n", p.Memory)
	fmt.Printf("摄像头:%s\n", p.Camera)
	fmt.Printf("系统:%s\n", p.System)
	fmt.Printf("电池:%s\n", p.Battery)
}

// PhoneBuilder 建造者接口:定义构建手机的步骤
type PhoneBuilder interface {
	SetBrand()   // 设置品牌
	SetCPU()     // 设置CPU
	SetMemory()  // 设置内存
	SetCamera()  // 设置摄像头
	SetSystem()  // 设置系统
	SetBattery() // 设置电池
	GetPhone() *Phone
}

// EntryLevelPhoneBuilder 具体建造者:入门级手机
type EntryLevelPhoneBuilder struct {
	phone *Phone
}

func NewEntryLevelPhoneBuilder() *EntryLevelPhoneBuilder {
	return &EntryLevelPhoneBuilder{
		phone: &Phone{},
	}
}

func (e *EntryLevelPhoneBuilder) SetBrand() {
	e.phone.Brand = "红米"
}

func (e *EntryLevelPhoneBuilder) SetCPU() {
	e.phone.CPU = "骁龙695"
}

func (e *EntryLevelPhoneBuilder) SetMemory() {
	e.phone.Memory = "6GB + 128GB"
}

func (e *EntryLevelPhoneBuilder) SetCamera() {
	e.phone.Camera = "4800万像素单摄"
}

func (e *EntryLevelPhoneBuilder) SetSystem() {
	e.phone.System = "MIUI 15"
}

func (e *EntryLevelPhoneBuilder) SetBattery() {
	e.phone.Battery = "5000mAh"
}

func (e *EntryLevelPhoneBuilder) GetPhone() *Phone {
	return e.phone
}

// FlagshipPhoneBuilder 具体建造者:旗舰级手机
type FlagshipPhoneBuilder struct {
	phone *Phone
}

func NewFlagshipPhoneBuilder() *FlagshipPhoneBuilder {
	return &FlagshipPhoneBuilder{
		phone: &Phone{},
	}
}

func (f *FlagshipPhoneBuilder) SetBrand() {
	f.phone.Brand = "小米"
}

func (f *FlagshipPhoneBuilder) SetCPU() {
	f.phone.CPU = "骁龙8 Gen3"
}

func (f *FlagshipPhoneBuilder) SetMemory() {
	f.phone.Memory = "12GB + 512GB"
}

func (f *FlagshipPhoneBuilder) SetCamera() {
	f.phone.Camera = "1亿像素三摄(OIS光学防抖)"
}

func (f *FlagshipPhoneBuilder) SetSystem() {
	f.phone.System = "MIUI 15(基于Android 14)"
}

func (f *FlagshipPhoneBuilder) SetBattery() {
	f.phone.Battery = "5500mAh(120W快充)"
}

func (f *FlagshipPhoneBuilder) GetPhone() *Phone {
	return f.phone
}

// Director 指挥者:控制构建流程
type Director struct {
	builder PhoneBuilder
}

func NewDirector(builder PhoneBuilder) *Director {
	return &Director{
		builder: builder,
	}
}

func (d *Director) Construct() {
	d.builder.SetBrand()
	d.builder.SetCPU()
	d.builder.SetMemory()
	d.builder.SetCamera()
	d.builder.SetSystem()
	d.builder.SetBattery()
}

func main() {
	// 构建入门级手机
	entryBuilder := NewEntryLevelPhoneBuilder()
	entryDirector := NewDirector(entryBuilder)
	entryDirector.Construct()
	entryPhone := entryBuilder.GetPhone()
	fmt.Println("=== 入门级手机 ===")
	entryPhone.ShowInfo()

	// 构建旗舰级手机
	flagshipBuilder := NewFlagshipPhoneBuilder()
	flagshipDirector := NewDirector(flagshipBuilder)
	flagshipDirector.Construct()
	flagshipPhone := flagshipBuilder.GetPhone()
	fmt.Println("\n=== 旗舰级手机 ===")
	flagshipPhone.ShowInfo()
}

执行结果

bash 复制代码
# 运行命令
go run builder_pattern.go

# 输出
=== 入门级手机 ===
手机配置:
品牌:红米
CPU:骁龙695
内存:6GB + 128GB
摄像头:4800万像素单摄
系统:MIUI 15
电池:5000mAh

=== 旗舰级手机 ===
手机配置:
品牌:小米
CPU:骁龙8 Gen3
内存:12GB + 512GB
摄像头:1亿像素三摄(OIS光学防抖)
系统:MIUI 15(基于Android 14)
电池:5500mAh(120W快充)

三、Go风格建造者模式

函数式选项模式(Functional Options)

go 复制代码
package main

import "fmt"

// Computer 使用函数式选项模式
type Computer struct {
    CPU     string
    Memory  string
    Storage string
    GPU     string
    Monitor string
    Network string
}

// ComputerOption 选项函数类型
type ComputerOption func(*Computer)

// 选项函数
func WithCPU(cpu string) ComputerOption {
    return func(c *Computer) {
        c.CPU = cpu
    }
}

func WithMemory(memory string) ComputerOption {
    return func(c *Computer) {
        c.Memory = memory
    }
}

func WithStorage(storage string) ComputerOption {
    return func(c *Computer) {
        c.Storage = storage
    }
}

func WithGPU(gpu string) ComputerOption {
    return func(c *Computer) {
        c.GPU = gpu
    }
}

func WithMonitor(monitor string) ComputerOption {
    return func(c *Computer) {
        c.Monitor = monitor
    }
}

func WithNetwork(network string) ComputerOption {
    return func(c *Computer) {
        c.Network = network
    }
}

// NewComputer 构造函数
func NewComputer(opts ...ComputerOption) *Computer {
    computer := &Computer{
        // 默认值
        CPU:     "Intel i5",
        Memory:  "8GB",
        Storage: "256GB SSD",
        Network: "1G Ethernet",
    }
    
    for _, opt := range opts {
        opt(computer)
    }
    
    return computer
}

func (c *Computer) Show() {
    fmt.Printf("电脑配置:\n")
    fmt.Printf("  CPU: %s\n", c.CPU)
    fmt.Printf("  内存: %s\n", c.Memory)
    fmt.Printf("  存储: %s\n", c.Storage)
    fmt.Printf("  网络: %s\n", c.Network)
    if c.GPU != "" {
        fmt.Printf("  显卡: %s\n", c.GPU)
    }
    if c.Monitor != "" {
        fmt.Printf("  显示器: %s\n", c.Monitor)
    }
    fmt.Println()
}

// 使用示例
func functionalOptionsExample() {
    fmt.Println("=== 函数式选项模式示例 ===")
    
    // 默认配置
    defaultPC := NewComputer()
    defaultPC.Show()
    
    // 游戏配置
    gamingPC := NewComputer(
        WithCPU("Intel i9-13900K"),
        WithMemory("32GB DDR5"),
        WithStorage("2TB NVMe SSD"),
        WithGPU("NVIDIA RTX 4090"),
        WithMonitor("27寸 4K 144Hz"),
        WithNetwork("2.5G Ethernet"),
    )
    gamingPC.Show()
    
    // 服务器配置
    serverPC := NewComputer(
        WithCPU("AMD EPYC 7713"),
        WithMemory("128GB DDR4 ECC"),
        WithStorage("4TB NVMe SSD"),
        WithNetwork("10G Ethernet"),
    )
    serverPC.Show()
}

func main() {
    functionalOptionsExample()
}

执行结果如下:

bash 复制代码
=== 函数式选项模式示例 ===
电脑配置:
  CPU: Intel i5
  内存: 8GB
  存储: 256GB SSD
  网络: 1G Ethernet

电脑配置:
  CPU: Intel i9-13900K
  内存: 32GB DDR5
  存储: 2TB NVMe SSD
  网络: 2.5G Ethernet
  显卡: NVIDIA RTX 4090
  显示器: 27寸 4K 144Hz

电脑配置:
  CPU: AMD EPYC 7713
  内存: 128GB DDR4 ECC
  存储: 4TB NVMe SSD
  网络: 10G Ethernet
相关推荐
崎岖Qiu5 小时前
【设计模式笔记11】:简单工厂模式优缺分析
java·笔记·设计模式·简单工厂模式
你的人类朋友15 小时前
设计模式有哪几类?
前端·后端·设计模式
Yeats_Liao15 小时前
Go Web 编程快速入门 10 - 数据库集成与ORM:连接池、查询优化与事务管理
前端·数据库·后端·golang
你的人类朋友16 小时前
适配器模式:适配就完事了bro!
前端·后端·设计模式
紫荆鱼19 小时前
设计模式-适配器模式(Adapter)
c++·设计模式·适配器模式
Tony Bai20 小时前
【Go模块构建与依赖管理】01 前世今生:从 GOPATH 的“混乱”到 Go Modules 的“秩序”
开发语言·后端·golang
gopyer20 小时前
Go语言2D游戏开发入门004:零基础打造射击游戏《太空大战》3
golang·go·游戏开发