# 設計模式(單一職責的類別)
## 程式碼的組織
* 修改不會產生意想不到的副作用(所有橡膠鴨子一起飛)
* 輕微的需求變化也只需要輕微的程式碼修改(不要為每個鴨子行為複寫)
* 既有的程式碼易於重複使用
* 最簡單的修改方式是增加其自身也易於修改的程式碼
## 程式碼的特點
* 透明性:程式碼的修改結果應該顯而易見,無論是在其自身修改處或是在遠處依賴於它的程式碼
* 合理性:任何修改所產生的成本都應該與修改所帶來的效益成正比
* 可用性:既有得程式碼在有所不同以及非預期的上下文中仍然保持可用性
* 典範性:程式碼本身應該鼓勵那些為延續這些特點而對它進行的修改
---
想利用程式碼計算ratio
```ruby=
chainring = 52 #齒輪牙的數量
cog = 11
ratio = chainring / cog.to_f
chainring = 30 #齒輪牙的數量
cog = 27
ratio = chainring / cog.to_f
```
重複程式碼:建立類別
```ruby=
class Gear
attr_reader :chainring, :cog
def initialize(chainring, cog)
@chainring = chainring
@cog = cog
end
def ratio
chainring / cog.to_f
end
end
#只需要給予兩個數值,就可以得到結果
Gear.new(52, 11).ratio
Gear.new(30, 27).ratio
```
需求變更:車輪尺寸更動
```ruby=
class Gear
attr_reader :chainring, :cog, :rim, :tire
def initialize(chainring, cog, rim, tire)
@chainring = chainring
@cog = cog
@rim = rim
@tire = tire
end
def ratio
chainring / cog.to_f
end
def gear_inches
ratio * (rim + (tire * 2))
end
end
#需要輸入更多數值,才能得到結果
Gear.new(52, 11, 26, 1.5).gear_inches
#噴錯給你看
Gear.new(52, 11).ratio
```
所以齒輪有需要理解輪胎嗎?
應用單一職責實現類別運作(內聚:類別內容都與中心目標相關聯)
* 別誤會了,單一職責並非侷限工作,而是要讓你的工作郖跟中心目標有所關聯)
1. 隱藏實例變數
```ruby=
attr_reader
#https://www.rubyguides.com/2018/11/attr_accessor/
```
2. 隱藏資料結構
```ruby=
class ObscuringReferences
attr_reader :data
def initialize(data)
@data = data
end
def diameters
data.collect {|cell|
cell[0] + (cell[1] * 1)}
end
end
#必須知道data"是什麼"
```
## 實行單一職責
```ruby=
class Gear
attr_reader :chainring, :cog, :wheel
def initialize(chainring, cog, wheel = nil)
@chainring = chainring
@cog = cog
@wheel = wheel
end
def ratio
chainring / cog.to_f
end
def gear_inches
ratio * wheel.diameter
end
class Wheel
attr_reader :rim, :tire
def initialize(rim, tire)
@rim = rim
@tire = tire
end
def diameter
rim + (tire * 2)
end
def circumference
diameter * Math::PI
end
end
@wheel = Wheel.new(26, 1.5)
Gear.nwe(52, 11, @wheel).gear_inches
Gear.nwe(52, 11).ratio
```