## 34.復合模式
看看下面的代碼 [iling_egg.rb](code/design_patterns/boiling_egg.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
48
49
50
51
52
53
54
55
56
57
58
59
60
```rb
|
```
require_relative "node.rb"
class BuyEggs < Node
attr_accessor :time_in_minutes
def initialize
@time_in_minutes = 15
super "Buy eggs"
end
end
class BoilEggs < Node
attr_accessor :time_in_minutes
def initialize
@time_in_minutes = 10
super "Boil eggs"
end
end
class PeelEggs < Node
attr_accessor :time_in_minutes
def initialize
@time_in_minutes = 3
super "Peel eggs"
end
end
class ServeEggs < Node
attr_accessor :time_in_minutes
def initialize
@time_in_minutes = 2
super "Serve eggs"
end
end
class BoiledEggs < Node
def initialize
super "Boiled eggs"
add_child BuyEggs.new
add_child BoilEggs.new
add_child PeelEggs.new
add_child ServeEggs.new
end
def total_time_in_minutes
total = 0
for child in self.children
total += child.time_in_minutes
end
total
end
end
boiled_eggs = BoiledEggs.new
puts "Time (in minutes) to make boiled eggs is #{boiled_eggs.total_time_in_minutes}."
```rb
|
```
輸出量
```rb
Time (in minutes) to make boiled eggs is 30.
```
在復合模式中,我們將一個類分為許多類。 假設需要以面向對象的方式表示煮雞蛋,我們可以將`BoiledEggs`編寫為如下所示的類。
```rb
class BoiledEggs < Node
def initialize
super "Boiled eggs"
add_child BuyEggs.new
add_child BoilEggs.new
add_child PeelEggs.new
add_child ServeEggs.new
end
def total_time_in_minutes
total = 0
for child in self.children
total += child.time_in_minutes
end
total
end
end
```
`BoiledEggs`繼承了一個名為`Node`的類,該類有助于構建樹結構。 稍后再討論`Node`類。 現在讓我們專注于復合模式。 如你在`initialize`方法中所見,在該類中`BoiledEggs`被劃分為許多類,即`BuyEggs`至`ServeEggs`,并且它們被作為子節點添加到`BoiledEggs`中。
如果你可以看到類`BuyEggs`如下所示:
```rb
class BuyEggs < Node
attr_accessor :time_in_minutes
def initialize
@time_in_minutes = 15
super "Buy eggs"
end
end
```
如果看到類`ServeEggs`,則如下所示:
```rb
class ServeEggs < Node
attr_accessor :time_in_minutes
def initialize
@time_in_minutes = 2
super "Serve eggs"
end
end
```
實際上,它看起來與`BuyEggs`非常相似,因此可以按照相似的方式處理這些類。 因此`BoiledEggs`就像是由不同對象組成的,可以用相似的方式對其進行處理。
現在`BoiledEggs`中的每個類都具有`time_in_minutes`屬性。 因此,如果我們需要以分鐘為單位計算制作煮雞蛋的總時間,我們要做的就是編寫一個函數`total_time_in_minutes`,如下所示
```rb
class BoiledEggs < Node
...
def total_time_in_minutes
total = 0
for child in self.children
total += child.time_in_minutes
end
total
end
end
```
因此,復合模式可以用于存在復雜對象的地方,可以將其功能分解為較小的對象,可以以非常相似的方式處理這些較小的對象,并將這些較小的對象放置在樹狀結構中。
談論樹結構,我們建立了一個名為`Node`的類,可以在文件 [node.rb](code/design_patterns/node.rb) 中找到該類。 你可以在下面看到它。
```rb
```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
```rb
|
```
class Node
attr_accessor :name, :parent, :children
def initialize name = "node"
@name = name
@parent = nil
@children = []
end
def to_s
"<Node: #{@name}, id: #{self.object_id}>"
end
def add_child node
children << node
node.parent = self
end
end
```rb
|
```
它具有一個稱為`add_child`的功能,通過它我們可以添加子元素。 你可以使用`parent`功能獲取節點的父節點。 要查看此節點類的工作方式,請看下面的代碼 [Composite.rb](code/design_patterns/composite.rb) :
```rb
```
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
```rb
|
```
# composite.rb
require_relative "node.rb"
n1 = Node.new "n1"
n2 = Node.new "n2"
n3 = Node.new "n3"
n1.add_child n2
n1.add_child n3
puts "children of #{n1} are:"
for node in n1.children
puts node
end
puts
puts "Parent of #{n3} is #{n3.parent}"
```rb
|
```
Output
```rb
children of <Node: n1, id: 47253445808700> are:
<Node: n2, id: 47253445808560>
<Node: n3, id: 47253445808360>
Parent of <Node: n3, id: 47253445808360> is <Node: n1, id: 47253445808700>
```
- 前言
- 紅寶石
- 先決條件
- 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.策略模式
- 贊助商
- 捐
- 人們怎么說
- 版權
- 取得這本書