一起学习 Go 语言设计模式之建造者模式(下)

简介: 在设计模式中,建造者模式就是解决如何将这些部件组装成一辆完整的汽车并返回给用户的设计模式。建造者模式为客户端返回的不是一个简单的产品,而是一个由多个部件组成的复杂产品。

Go 代码示例

代码组织结构如下:


image.png


  1. 首先创建 house.go 文件, 建立 House 这个产品基类,代码如下;
package main
type House struct {
  windowType string
  doorType   string
  swimPool   string
  floor      int
}


正像前文所说一眼,房子有窗户、门、游泳池、楼层等部分组成。


  1. 然后创建抽象创建者 iBuilder.go 文件,也是我们的建造者接口,分别定义 4 个 set  和 1 个 getHouse()  方法,代码如下:
package main
type IBuilder interface {
  setWindowType()
  setDoorType()
  setNumFloor()
  setSwimPool()
  getHouse() House
}
func getBuilder(builderType string) IBuilder {
  if builderType == "normal" {
    return newNormalBuilder()
  }
  if builderType == "cottages" {
    return newCottagesBuilder()
  }
  return nil
}


  1. 新建具体建造者:普通房子 normalBuilder.go,在这个文件中,因为 Go 语言没有继承的概念,所以也需要我们定义跟 House 相同的结构体,然后实现 normalHouse 的构建 :
package main
type NormalBuilder struct {
  windowType string
  doorType   string
  swimPool   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 = 3
}
func (b *NormalBuilder) setSwimPool() {
  b.swimPool = "None"
}
func (b *NormalBuilder) getHouse() House {
  return House{
    doorType:   b.doorType,
    windowType: b.windowType,
    swimPool:   b.swimPool,
    floor:      b.floor,
  }
}


  1. 跟上一步同理,新建别墅具体建设者 cottagesBuilder.go 文件,代码如下:
package main
type cottagesBuilder struct {
  windowType string
  doorType   string
  swimPool   string
  floor      int
}
func newCottagesBuilder() *cottagesBuilder {
  return &cottagesBuilder{}
}
func (b *cottagesBuilder) setWindowType() {
  b.windowType = "Glass Window"
}
func (b *cottagesBuilder) setDoorType() {
  b.doorType = "Steel Security Door"
}
func (b *cottagesBuilder) setNumFloor() {
  b.floor = 1
}
func (b *cottagesBuilder) setSwimPool() {
  b.swimPool = "Swimming Pool"
}
func (b *cottagesBuilder) getHouse() House {
  return House{
    doorType:   b.doorType,
    windowType: b.windowType,
    swimPool:   b.swimPool,
    floor:      b.floor,
  }
}
  1. 新建主管 director.go ,主管结构体内也是抽象建造者,其次主管有着 setBuilder()buildHouse() 的职责,最后主管负责安排负责对象的建造次序,比如先确定门、窗、楼层,再考虑是否需要加装泳池。最终代码如下:
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()
  d.builder.setSwimPool()
  return d.builder.getHouse()
}


6.新建一个 main.go 文件,测试我们的创建者模式是否正确:

package main
import (
  "fmt"
)
func main() {
  normalBuilder := getBuilder("normal")
  cottagesBuilder := getBuilder("cottages")
  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 SwimPool: %s\n", normalHouse.swimPool)
  fmt.Printf("Normal House Num Floor: %d\n", normalHouse.floor)
  director.setBuilder(cottagesBuilder)
  cottagesHouse := director.buildHouse()
  fmt.Printf("\nCottage House Door Type: %s\n", cottagesHouse.doorType)
  fmt.Printf("Cottage House Window Type: %s\n", cottagesHouse.windowType)
  fmt.Printf("Cottage House SwimPool: %s\n", cottagesHouse.swimPool)
  fmt.Printf("Cottage House Num Floor: %d\n", cottagesHouse.floor)
}


  1. 最后,我们使用命令运行整个包 go run .


这是输出结果图:


image.png

优缺点

优点:


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


缺点:


  • 由于该模式需要新增多个类, 因此代码整体复杂程度会有所增加。
相关文章
|
8月前
|
安全 Java 编译器
对比Java学习Go——基础理论篇
本章介绍了Java开发者学习Go语言的必要性。Go语言以简单、高效、并发为核心设计哲学,摒弃了传统的类继承和异常机制,采用组合、接口和多返回值错误处理,提升了代码清晰度与开发效率。Go直接编译为静态二进制文件,启动迅速、部署简便,其基于Goroutine和Channel的并发模型相较Java的线程与锁机制更轻量安全。此外,Go Modules简化了依赖管理,与Java的Maven/Gradle形成鲜明对比,提升了构建与部署效率。
582 1
|
7月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
391 2
|
8月前
|
存储 Java Go
对比Java学习Go——函数、集合和OOP
Go语言的函数支持声明与调用,具备多返回值、命名返回值等特性,结合`func`关键字与类型后置语法,使函数定义简洁直观。函数可作为一等公民传递、赋值或作为参数,支持匿名函数与闭包。Go通过组合与接口实现面向对象编程,结构体定义数据,方法定义行为,接口实现多态,体现了Go语言的简洁与高效设计。
260 4
|
8月前
|
存储 Java 编译器
对比Java学习Go——程序结构与变量
本节对比了Java与Go语言的基础结构,包括“Hello, World!”程序、代码组织方式、入口函数定义、基本数据类型及变量声明方式。Java强调严格的面向对象结构,所有代码需置于类中,入口方法需严格符合`public static void main(String[] args)`格式;而Go语言结构更简洁,使用包和函数组织代码,入口函数为`func main()`。两种语言在变量声明、常量定义、类型系统等方面也存在显著差异,体现了各自的设计哲学。
307 0
|
9月前
|
Cloud Native Go API
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
607 0
|
9月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
427 0
|
9月前
|
Cloud Native Java 中间件
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
469 0
|
9月前
|
Cloud Native Java Go
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
534 0
|
存储 缓存 安全
Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
`sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
|
存储 负载均衡 监控
如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
在数字化时代,构建高可靠性服务架构至关重要。本文探讨了如何利用Go语言的高效性、并发支持、简洁性和跨平台性等优势,通过合理设计架构、实现负载均衡、构建容错机制、建立监控体系、优化数据存储及实施服务治理等步骤,打造稳定可靠的服务架构。
527 1