2013-01-21 68 views
7

我在寻求设计模式的帮助。 我很习惯Java中的接口,我不知道如何在Ruby中获得类似的机制。它需要的是一种界面,它有一种方法,例如联系人。为了获得联系人,我需要对api进行调用,这可能是谷歌,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 

但我真的不知道,如果这是“红宝石的路要走”。

欢迎提出帮助,建议和指导。 Best, Phil

+0

可能重复:http://stackoverflow.com/questions/ 4437291/what-is-java-interface-equivalent-in-ruby – BentOnCoding

+0

使用heritance并使该函数在父类中引发错误。 – oldergod

回答

2

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

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

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

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 

上。这里Implcreate方法是用于默认地将Impl实例的工厂方法是,在从给定模块的方法中增加了。只要确保模块实现相同的方法名称并返回兼容的值。

+0

不错的做法! – dc10

4

战略模式可以应用在这里

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 
1

我真的很喜欢@Bui的安和的答案,但我会添加以下内容:

我喜欢这种方法有很多,特别的饲养基类Provider中的错误。不过,我认为Impl中的案例陈述并不是很好的策略模式。它违反了单一目的原则,因为它使实施负责跟踪所有可能的提供者。它也违反了开放扩展类的开放原则,但不能改变,因为当你添加一个新的提供者时你必须改变case语句。

为什么不只是做

impl = Impl.new(Google.new) 

自养 “未知供应商” 的错误,将采取这种方式的护理:

impl = Impl.new(BadProvider.new) => Error