## 35.建造者模式
假設你正在為網站提供高度定制化功能的計算機制造商編寫一款軟件。 一臺計算機可以有很多零件,它們可以變化,因此有很多組合。 因此,我們不是將所有這些代碼放在一個單一的大型計算機類中,而是創建了一個名為 builder 的類,在這種情況下,我們創建了一個名為`ComputerBuilder`的類,該類承擔創建定制計算機的任務,并可能簡化創建或創建過程。 構建過程也是如此。
假設我們需要不同類型的 CPU 來構建計算機,為此,我們編寫了三種類型的 CPU 類,如下所示 [cpus.rb](code/design_patterns/builder/cpus.rb) 。
```rb
```
1
2
3
4
5
6
7
8
9
10
11
```rb
|
```
class CPU
# cpu stuff...
end
class BasicCPU < CPU
# basic cpu stuff...
end
class TurboCPU < CPU
# trubo fast cpu stuff...
end
```rb
|
```
計算機可能需要驅動器,我們也為此編寫了一個類,如果你看到下面的代碼 [drive.rb](code/design_patterns/builder/drive.rb) ,則為該驅動器提供了一個類以及一個可用于自定義的初始化程序 在一定程度上。
```rb
```
1
2
3
4
5
6
7
8
9
```rb
|
```
class Drive
attr_reader :type, :size, :writable
def initialize(type, size, writable)
@type = type
@size = size
@writable = writable
end
end
```rb
|
```
以類似的方式,下面我們在[母板.rb](code/design_patterns/builder/motherboard.rb) 中為母板編碼。
```rb
```
1
2
3
4
5
6
7
8
```rb
|
```
class Motherboard
attr_accessor :cpu, :memory_size
def initialize(cpu = BasicCPU.new, memory_size = 1000)
@cpu = cpu
@memory_size = memory_size
end
end
```rb
|
```
現在讓我們看一下`Computer`類(在 [computer.rb](code/design_patterns/builder/computer.rb) 中),這與`Drive`和`Motherboard`類非常相似。 我們的目標是了解構建器模式,因此繼續前進。
```rb
```
1
2
3
4
5
6
7
8
9
```rb
|
```
class Computer
attr_accessor :display, :motherboard, :drives
def initialize(display = :crt, motherboard = Motherboard.new, drives = [])
@display = display
@motherboard = motherboard
@drives = drives
end
end
```rb
|
```
現在,讓我們分析一下本節的英雄`ComputerBuilder`類。 瀏覽下面的代碼,我們將很快討論。
```rb
```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
```rb
|
```
class ComputerBuilder
attr_reader :computer
def initialize
@computer = Computer.new
end
def turbo(_has_turbo_cpu = true)
@computer.motherboard.cpu = TurboCPU.new
end
def display(display)
@computer.display = display
end
def memory_size(size_in_mb)
@computer.motherboard.memory_size = size_in_mb
end
def add_cd(writable = false)
@computer.drives << Drive.new(:cd, 760, writable)
end
def add_dvd(writable = false)
@computer.drives << Drive.new(:dvd, 4700, writable)
end
def add_hard_disk(size_in_mb)
@computer.drives << Drive.new(:hard_disk, size_in_mb, true)
end
def method_missing(name, *args)
words = name.to_s.split('_')
return super(name, *args) unless words.shift == 'add'
words.each do |word|
next if word == 'and'
add_cd if word == 'cd'
add_dvd if word == 'dvd'
add_hard_disk(100_000) if word == 'harddisk'
turbo if word == 'turbo'
end
end
def computer
raise 'Not enough memory.' if @computer.motherboard.memory_size < 250
raise 'Too many drives.' if @computer.drives.size > 4
@computer
end
end
```rb
|
```
在上面的程序中,第 4 行中確實有`initialize`方法,但是如果你查看第 44 行,則在方法`computer`中將返回`Computer`實例。 如果你看到的是同一功能,那么如果沒有足夠的內存,或者如果計算機中添加了太多磁盤,則我們有代碼引發異常。 因此,這是構建器模式的另一個優點,在該模型中,如果不滿足特定條件,就可以防止構建復雜的對象。
在構建器中,你具有`display`,`memory_size`之類的方法,以及名為`turbo`的函數來設置顯示,內存和 CPU 類型的參數。 我們還具有`add_cd`,`add_dvd`和`add_hard_disk`之類的功能,可將這些內容添加到我們正在構建的計算機中。
現在讓我們看一下將所有內容組合在一起的程序。 看看下面的程序 [main.rb](code/design_patterns/builder/main.rb) ,鍵入或復制并執行它。
```rb
```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
```rb
|
```
require_relative 'cpus'
require_relative 'drive'
require_relative 'motherboard'
require_relative 'computer'
require_relative 'computer_builder'
builder = ComputerBuilder.new
builder.turbo
builder.display(:lcd)
builder.add_cd
builder.add_dvd(true)
builder.add_hard_disk(100_000)
# manufacture 10 computers using the builder
computers = []
10.times { computers << builder.computer.clone }
computers.each { |computer| puts computer }
# computer must have at least 250 MB of memory
builder = ComputerBuilder.new
builder.memory_size(249)
begin
builder.computer
rescue Exception => e
puts e.message
end
# computer must have at most 4 drives
builder = ComputerBuilder.new
builder.add_cd
builder.add_dvd
builder.add_hard_disk(1000)
builder.add_cd
builder.add_dvd
begin
builder.computer
rescue Exception => e
puts e.message
end
# use magic method to rapidly build a computer
puts 'Computer built with magic method builder'
builder = ComputerBuilder.new
builder.add_cd_and_dvd_and_harddisk_and_turbo
computer = builder.computer
puts "CPU: #{computer.motherboard.cpu.class}"
computer.drives.each { |drive| puts "Drive: #{drive.type}" }
```rb
|
```
輸出量
```rb
#<Computer:0x0000564155728610>
#<Computer:0x0000564155728598>
#<Computer:0x0000564155728570>
#<Computer:0x0000564155728548>
#<Computer:0x0000564155728520>
#<Computer:0x00005641557284f8>
#<Computer:0x00005641557284d0>
#<Computer:0x00005641557284a8>
#<Computer:0x0000564155728430>
#<Computer:0x0000564155728408>
Not enough memory.
Too many drives.
Computer built with magic method builder
CPU: TurboCPU
Drive: cd
Drive: dvd
Drive: hard_disk
```
現在讓我們看看它是如何工作的。 從 1-5 行:
```rb
require_relative 'cpus'
require_relative 'drive'
require_relative 'motherboard'
require_relative 'computer'
require_relative 'computer_builder'
```
我們需要該程序正常運行所需的文件。 在下面顯示的以下幾行中,我們創建一個名為`builder`的`ComputerBuilder`實例,該實例具有 Turbo CPU,LCD 顯示屏,一個 CD 播放器,一個可寫 DVD 和 100,000 MB 的硬盤:
```rb
builder = ComputerBuilder.new
builder.turbo
builder.display(:lcd)
builder.add_cd
builder.add_dvd(true)
builder.add_hard_disk(100_000)
```
現在,使用此`builder`,我們可以克隆 <sup class="footnote">[ [67](#_footnotedef_67 "View footnote.") ]</sup> 以創建任意數量的計算機。 在下面的代碼中,我們創建 10 個計算機克隆并打印它們
```rb
# manufacture 10 computers using the builder
computers = []
10.times { computers << builder.computer.clone }
computers.each { |computer| puts computer }
```
| | 假設你正在編寫游戲,并且需要創建 10 個對象,這種模式將非常方便。 |
現在,讓我們測試如果內存不足則將引發異常的代碼。 看下面的代碼
```rb
# computer must have at least 250 MB of memory
builder = ComputerBuilder.new
builder.memory_size(249)
begin
builder.computer
rescue Exception => e
puts e.message
end
```
在上面的代碼中,我們在`builder = ComputerBuilder.new`中創建一個計算機生成器,接下來我們在`builder.memory_size(249)`行中故意分配低內存,在`begin` `end`塊中,我們嘗試從`builder`創建一個`Computer`實例。 使用`builder.computer`并確定會引發 ans 異常,該異常會被`rescue`下的`puts e.message`語句捕獲并打印出來。 在輸出中,我們將得到以下消息:
```rb
Not enough memory.
```
我們以類似的方式嘗試構建一臺具有五個驅動器的計算機,即 2 個 CD,2 個 DVD 和 1 個硬盤。 在`ComputerBuilder`類中,我們將驅動器的最大數量限制為 4,因此下面的代碼段將引發錯誤:
```rb
# computer must have at most 4 drives
builder = ComputerBuilder.new
builder.add_cd
builder.add_dvd
builder.add_hard_disk(1000)
builder.add_cd
builder.add_dvd
begin
builder.computer
rescue Exception => e
puts e.message
end
```
捕獲并打印了此錯誤,因此我們得到以下輸出:
```rb
Too many drives.
```
### 35.1。 行使
你現在了解了構建器模式。 如果你想進一步探索,請看下面的代碼
```rb
# use magic method to rapidly build a computer
puts 'Computer built with magic method builder'
builder = ComputerBuilder.new
builder.add_cd_and_dvd_and_harddisk_and_turbo
computer = builder.computer
puts "CPU: #{computer.motherboard.cpu.class}"
computer.drives.each { |drive| puts "Drive: #{drive.type}" }
```
該代碼產生以下輸出
```rb
Computer built with magic method builder
CPU: TurboCPU
Drive: cd
Drive: dvd
Drive: hard_disk
```
現在,在`ComputerBuilder`類中查看`method_missing`方法,并嘗試解釋`builder.add_cd_and_dvd_and_harddisk_and_turbo`語句的工作方式。
- 前言
- 紅寶石
- 先決條件
- 1.安裝 Ruby
- 2.在線資源
- 3.入門
- 4.比較與邏輯
- 5.循環
- 6.數組
- 7.哈希和符號
- 8.范圍
- 9.功能
- 10.可變范圍
- 11.類&對象
- 12.安全導航
- 13.打破大型程序
- 14.結構和 OpenStruct
- 15. Rdoc
- 16. Ruby 樣式指南
- 17.模塊和混入
- 18.日期和時間
- 19.文件
- 20. Proc,Lambda 和塊
- 21.多線程
- 22.異常處理
- 23.正則表達式
- 24.寶石
- 25.元編程
- 26.基準
- 27.測試驅動開發
- 28.觀察者模式
- 29.模板模式
- 30.工廠模式
- 31.裝飾圖案
- 32.適配器模式
- 33.單例模式
- 34.復合模式
- 35.建造者模式
- 36.策略模式
- 贊助商
- 捐
- 人們怎么說
- 版權
- 取得這本書