是的,我們的車子確實需要輪子來進行移動,這點無法分割的一部分我承認,但是總會有更好的方式來管理這種情況。那就是孤立相依性
!既然我們沒辦法把它切割乾淨,那反其道而行,要依賴就要把關係處理好(更好維護的方式)所以因為前人的智慧,我們可以將這段程式碼修改為下列範例:
class Car
attr_reader :name, :color, :wheels, :type
def initialize(info = {})
@name = info[:name] || '未命名'
@color = info[:color] || '藍'
@type = info[:type] || '房車'
external_wheels(wheels)
end
def external_wheels(external_wheels)
@wheels = external_wheels || Wheels.new
end
def info
puts "#{name},這輛車子是#{@color}色的,類型為#{@type},輪子有#{@wheels.quantity}個。"
end
end
class Wheels
attr_reader :color, :quantity, :type
def initialize(info = {})
@color = info[:color] || '黑'
@quantity = info[:quantity] || 4
@type = info[:type] || '道路'
end
def info
puts "這台車的輪胎規格為#{@type}胎,顏色為#{@color}色,共有#{@quantity}個輪胎。"
end
end
compact_car = Car.new(name: '發財車', type: '貨車')
compact_car.info # => 發財車,這輛車子是藍色的,類型為貨車,輪子有4個。
compact_car.wheels.info # => 這台車的輪胎規格為道路胎,顏色為黑色,共有4個輪胎。
super_car = Car.new(name: '佛拉利', color: '紅', type: '跑車',
wheels: Wheels.new(color: '銀', type: '賽道'))
super_car.info # => 佛拉利,這輛車子是紅色的,類型為跑車,輪子有4個。
super_car.wheels.info # => 這台車的輪胎規格為賽道胎,顏色為銀色,共有4個輪胎。
有發現差異了嗎?我們把在 Car
類別中的 initialize
方法中,我們把先前的:
@wheels = info[:wheels] || Wheels.new
改寫為:
external_wheels(wheels)
然後在 Car
類別中新增一個方法:
def external_wheels(external_wheels)
@wheels = external_wheels || Wheels.new
end
為什麼要這樣寫呢?因為如剛剛我說,我們目的是要把引用外部類別 Wheels
抽離出來成一個獨立的方法。這樣對我們來說有什麼好處嗎?根據古人的智慧把外部類別隔離成一個方法有以下好處: