[go] 生成器模式

简介: [go] 生成器模式

生成器模式


生成器模式建议将对象构造代码从产品类中抽取出来, 并将其放在一个名为生成器的独立对象中。


模型说明



  • 生成器 (Builder) 接口声明在所有类型生成器中通用的产品构造步骤。
  • 具体生成器 (Concrete Builders) 提供构造过程的不同实现。 具体生成器也可以构造不遵循通用接口的产品。
  • 产品 (Products) 是最终生成的对象。 由不同生成器构造的产品无需属于同一类层次结构或接口。
  • 主管 (Director) 类定义调用构造步骤的顺序, 这样你就可以创建和复用特定的产品配置。
  • 客户端 (Client) 必须将某个生成器对象与主管类关联。 一般情况下, 你只需通过主管类构造函数的参数进行一次性关联即可。 此后主管类就能使用生成器对象完成后续所有的构造任务。 但在客户端将生成器对象传递给主管类制造方法时还有另一种方式。 在这种情况下, 你在使用主管类生产产品时每次都可以使用不同的生成器。


优缺点


1.优点


  • 你可以分步创建对象,暂缓创建步骤或递归运行创建步骤。
  • 生成不同形式的产品时,你可以复用相同的制造代码。
  • *单一职责原则:*你可以将复杂构造代码从产品的业务逻辑中分离出来。


2.缺点


  • 由于该模式需要新增多个类,因此代码整体复杂程度会有所增加。


使用场景


  • 使用生成器模式可避免“重叠构造函数(telescoping constructor)”的出现。
  • 当你希望使用代码创建不同形式的产品(例如石头或木头房屋)时,可使用生成器模式。
  • 使用生成器构造组合树或其他复杂对象。


参考代码


使用建造普通房子以及别墅来模拟


iBuilder.go: 生成器接口


package main
type IBuilder interface {
  setWindowType()
  setDoorType()
  setNumFloor()
  getHouse() House
}
func getBuilder(builderType string) IBuilder {
  if builderType == "normal" {
    return newNormalBuilder()
  }
  if builderType == "villa" {
    return newVillaBuilder()
  }
  return nil
}


normalBuilder.go: 普通房子生成器


package main
type NormalBuilder struct {
    windowType string
    doorType   string
    floor      int
}
func newNormalBuilder() *NormalBuilder {
    return &NormalBuilder{}
}
func (b *NormalBuilder) setWindowType() {
    b.windowType = "Wooden Window"
}
func (b *NormalBuilder) setDoorType() {
    b.doorType = "Wooden Door"
}
func (b *NormalBuilder) setNumFloor() {
    b.floor = 2
}
func (b *NormalBuilder) getHouse() House {
    return House{
        doorType:   b.doorType,
        windowType: b.windowType,
        floor:      b.floor,
    }
}


villaBuilder.go: 别墅生成器


package main
type VillaBuilder struct {
  windowType string
  doorType   string
  floor      int
}
func newVillaBuilder() *VillaBuilder {
  return &VillaBuilder{}
}
func (b *VillaBuilder) setWindowType() {
  b.windowType = "Snow Window"
}
func (b *VillaBuilder) setDoorType() {
  b.doorType = "Snow Door"
}
func (b *VillaBuilder) setNumFloor() {
  b.floor = 1
}
func (b *VillaBuilder) getHouse() House {
  return House{
    doorType:   b.doorType,
    windowType: b.windowType,
    floor:      b.floor,
  }
}


house.go: 房子产品


package main
type House struct {
  windowType string
  doorType   string
  floor      int
}


director.go: 主管类


package main
type Director struct {
  builder IBuilder
}
func newDirector(b IBuilder) *Director {
  return &Director{
    builder: b,
  }
}
func (d *Director) setBuilder(b IBuilder) {
  d.builder = b
}
func (d *Director) buildHouse() House {
  d.builder.setDoorType()
  d.builder.setWindowType()
  d.builder.setNumFloor()
  return d.builder.getHouse()
}


main.go: 客户端


package main
import "fmt"
func main() {
  normalBuilder := getBuilder("normal")
  villaBuilder := getBuilder("villa")
  director := newDirector(normalBuilder)
  normalHouse := director.buildHouse()
  fmt.Printf("Normal House Door Type: %s\n", normalHouse.doorType)
  fmt.Printf("Normal House Window Type: %s\n", normalHouse.windowType)
  fmt.Printf("Normal House Num Floor: %d\n", normalHouse.floor)
  director.setBuilder(villaBuilder)
  villa := director.buildHouse()
  fmt.Printf("\nIgloo House Door Type: %s\n", villa.doorType)
  fmt.Printf("Igloo House Window Type: %s\n", villa.windowType)
  fmt.Printf("Igloo House Num Floor: %d\n", villa.floor)
}


output:


Normal House Door Type: Wooden Door
Normal House Window Type: Wooden Window
Normal House Num Floor: 2
Igloo House Door Type: Snow Door
Igloo House Window Type: Snow Window
Igloo House Num Floor: 1
相关文章
|
3月前
|
缓存 NoSQL Go
通过 SingleFlight 模式学习 Go 并发编程
通过 SingleFlight 模式学习 Go 并发编程
|
5天前
|
Go 调度 开发者
探索Go语言中的并发模式:goroutine与channel
在本文中,我们将深入探讨Go语言中的核心并发特性——goroutine和channel。不同于传统的并发模型,Go语言的并发机制以其简洁性和高效性著称。本文将通过实际代码示例,展示如何利用goroutine实现轻量级的并发执行,以及如何通过channel安全地在goroutine之间传递数据。摘要部分将概述这些概念,并提示读者本文将提供哪些具体的技术洞见。
|
26天前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
26天前
|
安全 Go 开发者
破译Go语言中的并发模式:从入门到精通
在这篇技术性文章中,我们将跳过常规的摘要模式,直接带你进入Go语言的并发世界。你将不会看到枯燥的介绍,而是一段代码的旅程,从Go的并发基础构建块(goroutine和channel)开始,到高级模式的实践应用,我们共同探索如何高效地使用Go来处理并发任务。准备好,让Go带你飞。
|
3月前
|
存储 Unix 测试技术
解释Go中常见的I/O模式
解释Go中常见的I/O模式
|
4月前
|
设计模式 Go
Go语言设计模式:使用Option模式简化类的初始化
在Go语言中,面对构造函数参数过多导致的复杂性问题,可以采用Option模式。Option模式通过函数选项提供灵活的配置,增强了构造函数的可读性和可扩展性。以`Foo`为例,通过定义如`WithName`、`WithAge`、`WithDB`等设置器函数,调用者可以选择性地传递所需参数,避免了记忆参数顺序和类型。这种模式提升了代码的维护性和灵活性,特别是在处理多配置场景时。
72 8
|
3月前
|
缓存 算法 Go
|
3月前
|
存储 Unix 测试技术
解释Go中常见的I/O模式
解释Go中常见的I/O模式
|
3月前
|
设计模式 Go
|
5天前
|
存储 JSON 监控
Viper,一个Go语言配置管理神器!
Viper 是一个功能强大的 Go 语言配置管理库,支持从多种来源读取配置,包括文件、环境变量、远程配置中心等。本文详细介绍了 Viper 的核心特性和使用方法,包括从本地 YAML 文件和 Consul 远程配置中心读取配置的示例。Viper 的多来源配置、动态配置和轻松集成特性使其成为管理复杂应用配置的理想选择。
23 2