2013-01-21 5 views
7

デザインパターンに関してお問い合わせしています。 私は非常にJavaのインターフェイスに慣れています、そして、私はどのようにRubyで同様のメカニズムを取得するのか分かりません。それが必要とするのは、ある方法を有する一種のインターフェースである。連絡先。連絡先を取得するには、私はAPIを呼び出す必要があります、これは、Google、linkedidまたは任意のwebserviceすることができます。 私は連絡方法を提供するインターフェイスを使いたいと思っています。私はその方法については何も知りたくありません。ルビーのインターフェイシークなデザインパターン

私の最初の試みは、この(擬似コード)のようになります。

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 

しかし、これは「どこへ行くルビーの道」である場合、私は、本当にわかりません。

ヘルプ、提案や提案を歓迎します。 ベスト、 フィル

+0

が重複する可能性:http://stackoverflow.com/questions/ 4437291/what-is-java-interface-with-ruby – BentOnCoding

+0

は、継承を使用して、親クラスで関数をエラーにします。 – oldergod

答えて

2

モジュールは、通常、複数のオブジェクトの共通の動作を除外するために使用されます。私はあなたがこのケースで必要とするのはダックタイピングだと信じています。 Javaソリューションのインターフェースを共有するすべてのクラスにメソッドcontactsを実装するだけです。

このソリューションでは、1つのコレクションにさまざまなタイプのオブジェクトを保持することができます。これらの共通インターフェイスオブジェクトを繰り返し使用する場合は、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

Strategyパターンは、私は本当に@Buiザ・ホアの答えのように、ここで

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

を適用することもできるが、私は次のように追加します:

私はこのアプローチをたくさん好き、特に調達を基本Providerクラスのエラー。しかし、私はImplのcase文が良い戦略パターンの使用であるとは思わない。すべての可能なプロバイダを追跡する責任を負うため、単一目的の原則に違反します。それはまた、拡張子が開かれていても変更されないクラスのオープン・クローズの原則に違反します。新しいプロバイダを追加するときには、case文を変更する必要があるからです。

ちょうど "不明者" エラーはこの方法の世話をされるだろう昇給ので

impl = Impl.new(Google.new) 

をしない理由:

impl = Impl.new(BadProvider.new) => Error 
関連する問題