I am asking for help regarding a design pattern. I am very used to interfaces in java, and I dont know how to get a similar mechanism in ruby. What it need is kind of interface which has a method e.g. contacts. In order to get contacts I need to make a call against an api, this could be google, linkedid or whatever webservice. So I d like to use an interface which provides me the contacts method and i dont want to know anything about the provider beyond.
My first attempt looks like this (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
But I am really not sure, if this is the "ruby way to go".
Help, suggestions and recommendations are welcome. Best, Phil
Strategy pattern could be applied here
class 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
I really like @Bui The Hoa's answer, but I'll add the following:
I like this approach a lot, especially the raising of the error in the base Provider class. However I don't think having the case statement in the Impl is good Strategy pattern use. It violates the single purpose principle as it makes the implementation responsible for keeping track of all possible provider. It also violates the open-close principle of classes being open to extension but not to change, because when you add a new providers you'd have to change the case statement.
Why not just do
impl = Impl.new(Google.new)
Since the raise "Unknown provider" error would be taken care of this way:
impl = Impl.new(BadProvider.new) => Error
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With