2013-01-21 29 views
7

Tôi yêu cầu trợ giúp về mẫu thiết kế. Tôi rất quen với giao diện trong java, và tôi không biết làm thế nào để có được một cơ chế tương tự trong ruby. Điều cần là loại giao diện có phương pháp, ví dụ: địa chỉ liên hệ. Để có được địa chỉ liên lạc tôi cần phải thực hiện cuộc gọi chống lại api, điều này có thể là google, linkedid hoặc bất kỳ dịch vụ web nào. Vì vậy, tôi muốn sử dụng một giao diện cung cấp cho tôi phương pháp liên lạc và tôi không muốn biết bất cứ điều gì về nhà cung cấp ngoài.mẫu thiết kế interfacelike trong ruby ​​

nỗ lực đầu tiên của tôi trông như thế này (pseudo code):

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 

Nhưng tôi thực sự không chắc chắn, nếu đây là "ruby con đường để đi".

Trợ giúp, đề xuất và đề xuất được hoan nghênh. Tốt nhất, Phil

+0

thể trùng lặp: http://stackoverflow.com/questions/ 4437291/what-là-java-interface-equivalent-in-ruby – BentOnCoding

+0

sử dụng di sản và làm cho hàm tăng lỗi trong lớp cha. – oldergod

Trả lời

2

Mô-đun thường được sử dụng để loại trừ hành vi chung của nhiều đối tượng. Tôi tin rằng tất cả những gì bạn cần trong trường hợp này là gõ vịt. Chỉ cần triển khai phương thức contacts trong tất cả các lớp sẽ chia sẻ giao diện trong giải pháp Java. Xin lưu ý rằng giải pháp này cho phép bạn giữ các đối tượng của các loại khác nhau trong một bộ sưu tập, và trong khi bạn lặp lại chúng (hoặc theo bất kỳ cách nào khác bạn muốn sử dụng các đối tượng giao diện phổ biến này), bạn chỉ cần gọi số contacts này phương pháp, không quan tâm họ thực sự là loại gì.

Nếu bạn cần một số hành vi chung trong tất cả các lớp triển khai giao diện này, bạn có thể tạo mô-đun dựa trên sự tồn tại của phương pháp contacts và bao gồm nó trong tất cả các lớp có thể sử dụng nó.

4

Có một số cách tiếp cận tốt cho điều này. Một là để đóng gói các chức năng khác nhau thành các module:

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 

Output:

contacts from Google 
contacts from LinkedIn 

Đây là phương pháp create trên Impl là một phương pháp nhà máy cho các trường hợp Impl biết thêm rằng trong những phương pháp từ các module nhất định. Chỉ cần đảm bảo rằng các mô-đun thực hiện cùng tên phương thức và trả về các giá trị tương thích.

+0

cách tiếp cận tốt đẹp! – dc10

4
mẫu

Chiến lược có thể được áp dụng ở đây

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

Tôi thực sự thích câu trả lời @Bui Hòa, nhưng tôi sẽ thêm như sau:

Tôi thích cách tiếp cận này rất nhiều, đặc biệt là việc nâng cao lỗi trong lớp Nhà cung cấp cơ sở. Tuy nhiên tôi không nghĩ rằng có tuyên bố trường hợp trong Impl là sử dụng mô hình Chiến lược tốt. Nó vi phạm nguyên tắc mục đích duy nhất vì nó làm cho việc thực hiện chịu trách nhiệm theo dõi tất cả các nhà cung cấp có thể. Nó cũng vi phạm nguyên tắc mở của các lớp mở để mở rộng nhưng không thay đổi, bởi vì khi bạn thêm một nhà cung cấp mới, bạn phải thay đổi tuyên bố trường hợp.

Tại sao không chỉ làm

impl = Impl.new(Google.new) 

Kể từ khi tăng "Unknown cung cấp dịch vụ" lỗi sẽ được đưa về chăm sóc theo cách này:

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