我有一個設計問題。如何讓一個班有條件地返回其他兩個班之一?
我正在用ruby編寫一個REST客戶端。由於我無法控制的原因,它必須擴展另一個使用我的網絡zookeeper實例進行服務查找的gem。我的客戶端使用用戶提供的層,並根據該值向zookeeper註冊中心查詢相應的服務url。
問題是我還需要能夠運行我的客戶端對本地運行的測試服務版本。當服務在本地運行時,zookeeper顯然不參與,所以我只需要能夠對本地主機資源url進行GET請求。
當用戶實例我的寶石,他們稱這樣的:
client = MyRestClient.new(tier: :dev)
或在本地模式
client = MyRestClient.new(tier: :local)
我想避免有條件黑客在MyRestClient構造函數(和所有的在MyRestClient中使用GET方法)根據:local
與:requests_via_the_zk_gem
來更改請求。
我正在尋找一個優雅和乾淨的方式來處理這種情況在Ruby中。
一個想法是創建兩個客戶端類,一個用於:local
,另一個用於:not_local
。但後來我不知道如何提供一個將返回正確客戶端對象的gem接口。
如果MyClient
有一個構造看起來是這樣的:
class MyClient
attr_reader :the_klass
def initialize(opts={})
if opts[:tier] == :local
@the_klass = LocalClass.new
else
@the_klass = ZkClass.new
end
@the_klass
end
end
然後我最終是這樣的:
test = MyClient.new(tier: :local)
=> #<MyClient:0x007fe4d881ed58 @the_klass=#<LocalClass:0x007fe4d883afd0>>
test.class
=> MyClient
test.the_klass.class
=> LocalClass
那些誰,然後用我的寶石將不得不作出這樣的方法調用:
@client = MyClient.new(tier: :local)
@client.the_klass.get
這看起來不對
我可以使用模塊來返回適當的類,但是然後我面臨着如何爲我的寶石提供單個公共接口的問題。我不能用.new實例化一個模塊。
我的感覺是,這是一個常見的面向對象問題,我還沒有碰到它。也有可能答案是在我面前凝視我,我還沒有找到它。
非常感謝任何幫助。
你在找什麼叫[工廠模式](http://en.wikipedia.org/wiki/Factory_method_pattern) – bjhaid
而不是使用'Class',我想你可以使用'Module',如果opts [:tier] ==:local,那麼包含LocalClient其他模塊包括ZkModule end'。 – huocp