建造者模式的实现代码

建造者模式(Builder Pattern),又称生成器模式,是较为复杂的创建者模式,它将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂对象的内部组成部分与装配方式,只需要知道所需的建造者类型即可。

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

package main
import (
	"fmt"
)
// house.go
// 房子(产品)
type House struct {
	windowType string
	doorType   string
	swimPool   string
	floor      int
}

// iBuilder.go
// 建造者接口(泛指工人)
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
}

// normalBuilder.go
// 普通房子具体建造者(普通工人)
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,
	}
}

// cottagesBuilder.go
// 别墅具体建设者(别墅工人)
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,
	}
}

// director.go
// 主管(工头)
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()
}

// main.go
// 具体工作
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.png

建造者模式的代码拆分

1.项目的准备工作

找到 go 的 GOPATH

$ go env		//可以查看 GOPATH

在 GOPATH 目录下创建3个文件夹

1.bin文件夹		-- 存放编译后的二进制文件

2.pkg文件夹		-- 存放编译后的库文件

3.src文件夹		-- 存放源码文件

2.创建文件夹

​ -- 在项目文件夹 builde_case 里创建新文件夹

​ builde -- 存放建造者的全部文件

2.png

3.接口文件 -- builde文件夹

文件1 -- ibuilder.go

package builde

// 建造者接口(泛指工人)
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
}

4.结构体文件 -- builde文件夹

1.产品

文件1 -- house.go

package builde

// 房子(产品)
type House struct {
	WindowType string
	DoorType   string
	SwimPool   string
	Floor      int
}

2.建造队

文件1 --normalbuilder.go

package builde

// 普通房子具体建造者(普通工人)
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,
	}
}

文件2 -- cottagesbuilder.go

package builde

// 别墅具体建设者(别墅工人)
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,
    }
}

文件3 -- director.go

package builde

// 主管(工头)
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()
}

5.主文件 -- main.go 在项目文件夹

package main

import (
	"design/builde_case/builde"
	"fmt"
)

// 具体工作
func main() {

	normalBuilder := builde.GetBuilder("normal")
	cottagesBuilder := builde.GetBuilder("cottages")

	director := builde.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)

}

终端输出

3.png

6.全部文件图

4.png

7.代码拆分总结

1.抄别人代码,容易出错

2.上网查找解决方案,找不到易烦

3.有基础可以分析,可以得到解决方案

4.其实,方案常常也不难

5.上面的方案:结构体、属性、方法、函数的首字母大写,不同包可以访问