成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從“汽車制造”生活案例到軟件的建造者模式

系統 OpenHarmony
構建者模式幫助我們構建復雜的對象,而不需要直接實例化它們的結構,或編寫它們所需的邏輯。想象一下,一個對象可能有幾十個字段,它們本身就是比較復雜的結構。

??想了解更多關于開源的內容,請訪問:??

??51CTO 開源基礎軟件社區??

??https://ost.51cto.com??

一、生活案例

沙師弟 : “大師兄,車是怎么建成的?。俊?/p>

大師兄:“從外部看,車由車身、座椅和輪胎,從內部又有引擎、方向盤、電路系統、剎車系統、冷卻系統等等組成,這些復雜的部件一般都不是一個廠商來完成的,而是將這些交付給汽車零部件制造商。不同的生產商來最終完成不同部件的生產,采購完整個零部件,最后在車間完成整個組裝。”

汽車這個復雜的對象就可以通過建造者模式來將部件和組裝過程分開,幫我們快速完成汽車的建造。

二、建造者模式

構建者模式幫助我們構建復雜的對象,而不需要直接實例化它們的結構,或編寫它們所需的邏輯。想象一下,一個對象可能有幾十個字段,它們本身就是比較復雜的結構。

現在,你有許多具有這些特征的對象,還可以有更多。我們不希望在包中寫創建所有這些對象的邏輯,而只在需要使用這些對象的地方寫好。

1、Go 中的對象實例

在 Go 語言中,實例的創建可以很簡單,比如只是簡單提供 ??{}?? ,然后讓實例的值為零;也可以很復雜,比如一個對象需要進行一些 API 調用,檢查狀態,并為其字段創建對象。

你也可以有一個由多個對象組成的對象,這在 Go 中是非常常見的,因為 Go 不支持繼承。

同時,你可以用同樣的技術來創造許多類型的對象。例如,你將使用幾乎相同的技術來建造一輛汽車和一輛公共汽車,只是它們的尺寸和座位數不同,所以我們為什么不重復使用建造過程呢?這就是建造者模式的用武之地了。

2、建造者模式的優點

  • 對復雜的創建進行抽象,以便將對象與對象的使用者進行分開
  • 通過填入字段和創建嵌入對象,一步步創建對象
  • 能夠在許多對象之間重復使用對象創建方法

3、交通工具制造的例子

建造者模式通常被描述為一個主管 director、幾個 Builder 和他們所創建的產品之間的關系。

我們來看關于汽車的例子,創建一個車輛建造器 Builder,建造車(Product)的過程或許會有一些差異,但對每一種車輛來說,整體的過程可以歸納為如下步驟:

  1. 選擇車輛類型
  2. 組裝結構
  3. 安裝車輪
  4. 放置座椅

如果你仔細思考,你可以重復通過這個步驟描述建造一輛騎車和一輛摩托車,在接下來的例子中,主管 director 的角色就是用 Manufacturing 變量進行表示。

4、設計思路

正如上述的描述那樣,我們必須處理一些 Builder 變量和一個獨立的 director . 主管 director 來領導實際建造者 Builder 的建造產品的過程。因此,對于一個車輛建造者的要求是:

  • 需要有一個制造對象來制造交通工具的一切
  • 當使用汽車建造者Builder 時,返回的車輛產品必須帶有 4 個輪子、5 個座椅和定義為Car 的結構體
  • 使用摩托車建造者時,返回的車輛產品必須帶有 2 個輪子、供 2 個人的座位和定義為Motorbike 的結構體
  • 任何BuilderProcess 建造者必須開放對車輛產品的修改功能

結構圖如下:

#打卡不停更# 從“汽車制造”生活案例到軟件的建造者模式-開源基礎軟件社區

三、測試驅動開發

根據前文的設計過程,我們將建造一個 director 變量:ManufacturingDirector , 以使用由汽車和摩托車產品建造器的建造過程。dierctor 是負責人,builder 是實際的建造者。

1、Builder 接口聲明

Builder 聲明如下:

package creational

type BuildProcess interface {
SetWheels() BuildProcess
SetSeats() BuildProcess
SetStructure() BuildProcess
GetVehicle() VehicleProduct
}
  • BuildProcess 接口定義了建造車輛所需的步驟,因此,各個車輛的Builder 必須實現這個接口。
  • 在每個SetXXX() 的函數,返回每一個構建的過程,然后將各個步驟連接起來,返回一個GetVehicle() 的方法。

2、Director 主管接口

ManufacturingDirector 主管接口可以來自接收不同的 Builder:

  • 然后有一個Construct() 方法使用Builder 來重復建造過程,后面會實現這個方法。
  • SetBuilder() 方法用于更換不同的Builder。
// 制作主管
type ManufacturingDirector struct{}
func (f *ManufacturingDirector) Construct() {// 建筑過程
}
func (f *ManufacturingDirector) SetBuilder(b BuildProcess) {// 選擇建造者
}

3、Product 產品結構體

產品是我們在制造出的最終對象。在上面的簡易例子中,我們假設一輛交通工具是由車輪、座椅和結構組成的。

// 產品
type VehicleProduct struct {
Wheels int
Seats int
Structure string
}

4、Builder 具體建造者

第一個 Builder 為 Car 建造者 Builder,需要我們實現定義在 BuildProcess 接口的方法:

// 汽車建造者
type CarBuilder struct{}

func (c *CarBuilder) SetWheels() BuildProcess {return nil
}
func (c *CarBuilder) SetSeats() BuildProcess {return nil
}
func (c *CarBuilder) SetStructure() BuildProcess {return nil
}
func (c *CarBuilder) GetVehicle() VehicleProduct {return VehicleProduct{}
}

同理,摩托車建造者如下:

// 摩托車建造者
type MotorBuilder struct{}

func (m *MotorBuilder) SetWheels() BuildProcess {return nil
}
func (m *MotorBuilder) SetSeats() BuildProcess {return nil
}
func (m *MotorBuilder) SetStructure() BuildProcess {return nil
}
func (m *MotorBuilder) GetVehicle() VehicleProduct {return VehicleProduct{}
}

最終,我們得到完整的 creational.go 文件:

package creational

// 建造過程
type BuildProcess interface {
SetWheels() BuildProcess
SetSeats() BuildProcess
SetStructure() BuildProcess
GetVehicle() VehicleProduct
}
// 制作主管
type ManufacturingDirector struct{}
func (f *ManufacturingDirector) Construct() {
// 等待實現
}
func (f *ManufacturingDirector) SetBuilder(b BuildProcess) {
// 等待實現
}
// 產品
type VehicleProduct struct {
Wheels int
Seats int
Structure string
}
// 汽車建造者
type CarBuilder struct{}

func (c *CarBuilder) SetWheels() BuildProcess {
return nil
}
func (c *CarBuilder) SetSeats() BuildProcess {
return nil
}
func (c *CarBuilder) SetStructure() BuildProcess {
return nil
}
func (c *CarBuilder) GetVehicle() VehicleProduct {
return VehicleProduct{}
}
// 摩托車建造者
type MotorBuilder struct{}
func (m *MotorBuilder) SetWheels() BuildProcess {
return nil
}
func (m *MotorBuilder) SetSeats() BuildProcess {
return nil
}
func (m *MotorBuilder) SetStructure() BuildProcess {
return nil
}
func (m *MotorBuilder) GetVehicle() VehicleProduct {
return VehicleProduct{}
}

5、編寫測試用例

針對上面編寫的建造過程,我們可以進行如下的測試,同目錄下創建 creational_test.go 文件。

1、首先是測試汽車建造過程,假定最終生產的汽車是具有 4 個輪子,5 個座位,然后結構是 Car 類型,寫入如下代碼:

package creational

import "testing"

func TestBuilderPattern(t *testing.T) {

manufacturingComplex := ManufacturingDirector{}

carBuilder := &CarBuilder{}
manufacturingComplex.SetBuilder(carBuilder)
manufacturingComplex.Construct()

car := carBuilder.GetVehicle()

if car.Wheels != 4 {
t.Errorf("Wheels on a car must be 4 and they were %d\n", car.Wheels)
}

if car.Structure != "Car" {
t.Errorf("Structure on a car must be 'Car' and was %s\n", car.Structure)
}

if car.Seats != 5 {
t.Errorf("Seats on a car must be 5 and they were %d\n", car.Seats)
}

}

我們寫了 3 個簡單的測試檢查是否建造出汽車類型。運行單元測試,結果如下:

$ go test -v .
=== RUN TestBuilderPattern
creational_test.go:16: Wheels on a car must be 4 and they were 0
creational_test.go:20: Structure on a car must be 'Car' and was
creational_test.go:24: Seats on a car must be 5 and they were 0
--- FAIL: TestBuilderPattern (0.00s)
FAIL
FAIL github.com/yuzhoustayhungry/GoDesignPattern/creational 0.860s
FAIL

如上顯示,3 個測試單元都顯示失敗,接著我們來看一下摩托車的單元測試怎么寫的。

2、摩托車 motorCycle 的單元測試如下:

motorBuilder := &MotorBuilder{}

manufacturingComplex.SetBuilder(motorBuilder)
manufacturingComplex.Construct()
motorCycle := motorBuilder.GetVehicle()
if motorCycle.Wheels != 2 {
t.Errorf("Wheels on a motorCycle must be 2 and they were %d\n",
motorCycle.Wheels)
}
if motorCycle.Structure != "MotorCycle" {
t.Errorf("Structure on a motorCycle must be 'MotorCycle' and was %s\n",
motorCycle.Structure)
}
if motorCycle.Seats != 2 {
t.Errorf("Seats on a motorCycle must be 2 and was %d\n", motorCycle.Seats)
}

建造過程跟 car 類似,我們只需要向 manufacturingComplex.SetBuilder(motorBuilder) 傳遞 motorBuilder 即可,我們假定摩托車有 2 個輪子,2 個座位,結構必須為 MotorCyle。

運行測試代碼,得到如下結果:

$ go test -v .
=== RUN TestBuilderPattern
creational_test.go:16: Wheels on a car must be 4 and they were 0
creational_test.go:20: Structure on a car must be 'Car' and was
creational_test.go:24: Seats on a car must be 5 and they were 0
creational_test.go:36: Wheels on a motorCycle must be 2 and they were 0
creational_test.go:41: Structure on a motorCycle must be 'MotorCycle' and was
creational_test.go:46: Seats on a motorCycle must be 2 and was 0
--- FAIL: TestBuilderPattern (0.00s)
FAIL
FAIL github.com/yuzhoustayhungry/GoDesignPattern/creational 0.595s
FAIL

可以看到,單元測試也是失敗的,因為我們還沒有完成實現具體的建造者模式。接下來就是具體實現的過程。

四、建造者模式 Go 實現

為了實現建造者,想必你也開始有了一點點自己的思路吧。再來實現我們之前創建的 creation.go 文件,全新的 creational.go 文件代碼如下:

package creational

// 建造過程
type BuildProcess interface {SetWheels() BuildProcess
SetSeats() BuildProcess
SetStructure() BuildProcess
GetVehicle() VehicleProduct
}
// 制作主管
type ManufacturingDirector struct {
builder BuildProcess
}
func (f *ManufacturingDirector) Construct() {//
f.builder.SetSeats().SetStructure().SetWheels()
}
func (f *ManufacturingDirector) SetBuilder(b BuildProcess) {//
f.builder = b
}
// 產品
type VehicleProduct struct {
Wheels int
Seats int
Structure string
}
// 汽車建造者
type CarBuilder struct {
v VehicleProduct
}
func (c *CarBuilder) SetWheels() BuildProcess {// return nil
c.v.Wheels = 4return c
}
func (c *CarBuilder) SetSeats() BuildProcess {// return nil
c.v.Seats = 5return c
}
func (c *CarBuilder) SetStructure() BuildProcess {// return nil
c.v.Structure = "Car"return c
}
func (c *CarBuilder) GetVehicle() VehicleProduct {// return VehicleProduct{}return c.v
}
// 摩托車建造者
type MotorBuilder struct {
v VehicleProduct
}
func (m *MotorBuilder) SetWheels() BuildProcess {// return nil
m.v.Wheels = 2return m
}
func (m *MotorBuilder) SetSeats() BuildProcess {// return nil
m.v.Seats = 2return m
}
func (m *MotorBuilder) SetStructure() BuildProcess {// return nil
m.v.Structure = "MotorCycle"return m
}
func (m *MotorBuilder) GetVehicle() VehicleProduct {// return VehicleProduct{}return m.v
}

更改后的 creational_test.go 文件如下:

package creational
import "testing"
func TestBuilderPattern(t *testing.T) {
manufacturingComplex := ManufacturingDirector{}
carBuilder := &CarBuilder{}
manufacturingComplex.SetBuilder(carBuilder)
manufacturingComplex.Construct()
car := carBuilder.GetVehicle()
if car.Wheels != 4 {
t.Errorf("Wheels on a car must be 4 and they were %d\n", car.Wheels)}
if car.Structure != "Car" {
t.Errorf("Structure on a car must be 'Car' and was %s\n", car.Structure)}
if car.Seats != 5 {
t.Errorf("Seats on a car must be 5 and they were %d\n", car.Seats)}
motorBuilder := &MotorBuilder{}
manufacturingComplex.SetBuilder(motorBuilder)
manufacturingComplex.Construct()
motorCycle := motorBuilder.GetVehicle()
if motorCycle.Wheels != 2 {
t.Errorf("Wheels on a motorCycle must be 2 and they were %d\n",
motorCycle.Wheels)}
if motorCycle.Structure != "MotorCycle" {
t.Errorf("Structure on a motorCycle must be 'MotorCycle' and was %s\n",
motorCycle.Structure)}
if motorCycle.Seats != 2 {
t.Errorf("Seats on a motorCycle must be 2 and was %d\n", motorCycle.Seats)}
}

實現完所有的方法之后,再看運行 go test -v . 執行后的測試結果:

$ go test -v .
=== RUN TestBuilderPattern
--- PASS: TestBuilderPattern (0.00s)
PASS
ok github.com/yuzhoustayhungry/GoDesignPattern/creational 0.255s

恭喜,至此,測試用例全部通過。你也可以看到,建造者模式是一個可重復的模式,但在 BuildProcess 接口的每個方法內,我們可以封裝盡可能多的復雜對象,這樣,用戶其實并不知道關于對象創建的細節。

五、建造者模式總結

就像制作汽車一樣,建造者模式的核心在于如何一步一步地構建一個包含多個組成部件的完整對象,使用相同的構建過程構建不同的產品。

在軟件開發過程中,如果需要創建復雜對象,并希望系統具備很好的靈活性和可擴展性,可以考慮使用建造者模式。

??想了解更多關于開源的內容,請訪問:??

??51CTO 開源基礎軟件社區??

??https://ost.51cto.com??。

責任編輯:jianghua 來源: 51CTO開源基礎軟件社區
相關推薦

2011-07-14 14:46:46

設計模式

2020-10-20 13:33:00

建造者模式

2021-10-26 00:21:19

設計模式建造者

2021-01-21 05:34:14

設計模式建造者

2021-04-14 09:02:22

模式 設計建造者

2021-06-10 19:09:05

模式代碼建造者

2021-05-11 08:54:59

建造者模式設計

2023-09-25 10:31:42

汽車行業數字化轉型

2023-09-22 10:51:12

智能制造數字化轉型

2024-02-19 08:38:34

建造者模式Android設計模式

2021-07-28 10:02:54

建造者模式代碼

2021-01-25 05:38:04

設計原理VueSubject

2012-05-02 14:22:25

戴爾Wraps技術踏板車

2021-04-19 21:25:48

設計模式到元

2023-09-25 13:07:27

2025-04-25 08:23:20

2012-05-01 08:38:47

制造

2025-04-22 02:00:00

芯片晶圓光刻機

2010-09-02 09:15:50

企業云計算

2018-07-24 11:35:29

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 羞羞涩涩在线观看 | av免费观看在线 | 国产精品毛片av | 伊人手机在线视频 | 91看片在线| 色香蕉在线 | 国产最新精品视频 | 亚洲经典一区 | 爱爱免费视频网站 | 欧美视频一区二区三区 | 中文字幕在线一区二区三区 | 在线亚洲免费 | 国产精品视频久久 | 91精品国产乱码久久久久久久久 | 91精品国产91久久久久久密臀 | 91社区在线观看高清 | 福利片在线观看 | 国产成人短视频在线观看 | 99国产欧美| 黑人精品欧美一区二区蜜桃 | 全免费a级毛片免费看视频免费下 | 成人在线一区二区三区 | 黄色毛片免费看 | 国产一区二区三区四 | 黄a大片 | 国产精品入口麻豆www | 91精品国产91久久综合桃花 | 欧美精品在线视频 | 四虎永久在线精品免费一区二 | 亚洲高清电影 | 久久精品久久久 | 欧美久久一级特黄毛片 | 欧产日产国产精品99 | 日日干日日操 | 欧美高清hd| 99精品欧美一区二区三区综合在线 | 国产在线视频一区 | 91xxx在线观看 | 久草成人 | 久色| 国产成人福利在线观看 |