我正在寻求有关设计模式的帮助。我非常习惯java中的接口,我不知道如何在ruby中获得类似的机制。它需要的是一种具有例如方法的接口。联系人。为了获得联系我需要打电话给api,这可能是google,linkedid或任何web服务。所以我想使用一个界面,它为我提供了联系方式,我不想知道任何关于提供者的信息。
我的第一次尝试看起来像这样(伪代码):
Module AbstractContact
def contacts
#do some stuff with @data
@data
end
end
class Impl
include AbstractContact
def build_provider(provider)
if provider == :google
#get the data from google
gdata= api_call
@data = gdata
elsif provider == :linkedin
end
end
end
c=Impl.new
c.build_provider
c.contacts
但我真的不确定,如果这是“红宝石的方式”。
欢迎提供帮助,建议和建议。最好,菲尔
战略模式可以在这里应用
def Provider
def contacts
raise "Abstract method called"
end
end
class Google < Provider
def contacts
data = # Google API call
end
end
class LinkedIn < Provider
def contacts
data = # LinkedIn API call
end
end
class Impl
def initialize(provider)
case provider
when :google
@provider = Google.new
when :linkedin
@provider = LinkedIn.new
else
raise "Unknown provider"
end
end
def contacts
@provider.contacts
end
end
impl = Impl.new(provider)
impl.contacts
有几个很好的方法。一种是将不同的功能封装到模块中:
module Google
def contacts
puts 'contacts from Google'
end
end
module LinkedIn
def contacts
puts 'contacts from LinkedIn'
end
end
class Impl
def self.create provider
o = new
o.extend(provider)
end
end
Impl.create(Google).contacts
Impl.create(LinkedIn).contacts
输出:
contacts from Google
contacts from LinkedIn
这里create
上的Impl
方法是Impl实例的工厂方法,它添加了给定模块的方法。只需确保模块实现相同的方法名称并返回兼容的值。
模块通常用于排除多个对象的常见行为。我相信在这种情况下你需要的只是鸭子打字。只需在Java解决方案中共享接口的所有类中实现方法contacts
。
请注意,此解决方案允许您将不同类型的对象保存在单个集合中,当您迭代它们时(或者您希望使用这些公共接口对象的任何其他方式),您只需调用此contacts
方法,而不是关心他们到底是什么类型的。
如果在实现此接口的所有类中需要一些常见行为,则可以创建基于contacts
方法存在的模块,并将其包含在可以使用它的所有类中。
我非常喜欢@Bui The Hoa的答案,但我会添加以下内容:
我非常喜欢这种方法,特别是在基类Provider类中引发错误。但是我不认为在Impl中使用case语句是好的策略模式使用。它违反了单一目的原则,因为它使实施负责跟踪所有可能的提供者。它还违反了开放式扩展但不改变的类的开放式原则,因为当你添加新的提供者时,你必须改变case语句。
为什么不这样做呢
impl = Impl.new(Google.new)
由于引发“未知提供者”错误将以这种方式处理:
impl = Impl.new(BadProvider.new) => Error