# 設計模式(單一職責的類別) ## 程式碼的組織 * 修改不會產生意想不到的副作用(所有橡膠鴨子一起飛) * 輕微的需求變化也只需要輕微的程式碼修改(不要為每個鴨子行為複寫) * 既有的程式碼易於重複使用 * 最簡單的修改方式是增加其自身也易於修改的程式碼 ## 程式碼的特點 * 透明性:程式碼的修改結果應該顯而易見,無論是在其自身修改處或是在遠處依賴於它的程式碼 * 合理性:任何修改所產生的成本都應該與修改所帶來的效益成正比 * 可用性:既有得程式碼在有所不同以及非預期的上下文中仍然保持可用性 * 典範性:程式碼本身應該鼓勵那些為延續這些特點而對它進行的修改 --- 想利用程式碼計算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 ```