9

我正在寻求有关设计模式的帮助。我非常习惯java中的接口,我不知道如何在ruby中获得类似的机制。它需要的是一种具有方法的接口,例如联系人。为了获得联系人,我需要对 api 进行调用,这可能是 google、linkedid 或任何网络服务。所以我想使用一个接口,它为我提供了联系人方法,我不想知道任何关于提供者的信息。

我的第一次尝试看起来像这样(伪代码):

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

但我真的不确定,这是否是“红宝石之路”。

欢迎帮助,建议和建议。最好的,菲尔

4

4 回答 4

6

策略模式可以在这里应用

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
于 2013-01-29T03:10:37.117 回答
4

有几种很好的方法。一种是将不同的功能封装到模块中:

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 实例的工厂方法,它添加来自给定模块的方法。只需确保模块实现相同的方法名称并返回兼容的值。

于 2013-01-21T16:51:10.607 回答
2

我真的很喜欢@Bui The Hoa 的回答,但我会添加以下内容:

我非常喜欢这种方法,尤其是在基础 Provider 类中引发错误。但是我不认为在 Impl 中有 case 语句是很好的策略模式使用。它违反了单一目的原则,因为它使实现负责跟踪所有可能的提供者。它还违反了类对扩展开放但不可更改的开闭原则,因为当您添加新的提供者时,您必须更改 case 语句。

为什么不只是做

impl = Impl.new(Google.new)

由于会以这种方式处理引发“未知提供者”错误:

impl = Impl.new(BadProvider.new) => Error
于 2014-07-03T00:51:25.947 回答
2

模块通常用于排除多个对象的共同行为。我相信在这种情况下你所需要的只是鸭式打字。只需contacts在 Java 解决方案中共享接口的所有类中实现方法。

请注意,此解决方案允许您将不同类型的对象保存在单个集合中,并且当您迭代它们(或以任何其他方式您想使用这些公共接口对象)时,您只需调用此contacts方法,而不关心什么类型他们真的是。

如果您需要在实现此接口的所有类中具有一些共同行为,您可以创建基于contacts方法存在的模块,并将其包含在可以使用它的所有类中。

于 2013-01-21T12:09:08.873 回答