[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Re: The Factory Method

Pat Maddox

5/10/2007 7:17:00 AM

On 5/10/07, Enrique Comba Riepenhausen <ecomba@mac.com> wrote:
> Hi everyone,
>
> as you know I started a few days ago the Ruby Patterns Wiki and now I
> am starting to put in some samples. As you know, although I am not
> new to software development, I am still a newbie in Ruby.
>
> I was thinking about the Factory Method Pattern and following came to
> my mind. If we follow the Pattern by the book (GoF) we would have
> following code (simplified for the purpose of clarity):
>
> class Product
> def hi
> "hello there"
> end
> end
>
> class ConcreteProduct < Product
> def hi
> "Hello from the concrete implementation"
> end
> end
>
> class Creator
> def create_product
> end
> end
>
> class ConcreteCreator < Creator
> def create_product
> ConcreteProduct.new
> end
> end
>
> Obviously this code strikes in Ruby (specially the creator class that
> doesn't make much sense to me). How would you people think this could
> be implemented in Ruby? Or better to say, what is the Ruby way to
> solve this intent of the Factory Method Pattern: Define an interface
> for creating an object, but let subclasses decide which class to
> instantiate. Factory Method lets a class defer instantiation to
> subclasses.

One clue is that the example is coded in Java, vs smalltalk. The
reason for that is that Smalltalk doesn't really have the problem
they're solving here. An "interface" is just going to be a bunch of
methods with the same method names and signatures.

I'm sure they discusss it in DP, but you don't need to implement this
pattern with an abstract class. That's just there because you want
common behavior. So how do you implement this pattern in Ruby?

class AmericanCoffeeShop
def make_coffee
Coffee.new :ingredients => [ :water, :mud ]
end
end

class ItalianCoffeeShop
def make_coffee
Espresso.new
end
end

Simple, you've implemented the factory method pattern. We have an
interface - make_coffee - and each class can instantiate an object of
whatever kind it wants.

If some client code needs to have a coffee made, you can just pass it
an instance of either of those classes and it'll run fine.

Shared behavior can be provided by a mixin (whereas in Java you need a
superclass).

module CoffeeProvider
def order
take_payment
give_change
make_coffee
end
end

class AmericanCoffeeShop
include CoffeeProvider

def make_coffee
Coffee.new :ingredients => [ :water, :mud ]
end
end

class ItalianCoffeeShop
include CoffeeProvider

def make_coffee
Espresso.new
end
end

Now we've achieved the desired behavior. We've defined the high-level
behavior of taking an order, but placed the responsibility on
lower-level implementation details in another class. Now anyone can
come along and write a class that knows how to provide an order of
coffee, all without any foresight from the initial author of
CoffeeProvider.

Pat

3 Answers

Enrique Comba Riepenhausen

5/10/2007 7:25:00 AM

0

Hey Pat!

On 10 May 2007, at 09:16, Pat Maddox wrote:

>
> One clue is that the example is coded in Java, vs smalltalk. The
> reason for that is that Smalltalk doesn't really have the problem
> they're solving here. An "interface" is just going to be a bunch of
> methods with the same method names and signatures.
>
> I'm sure they discusss it in DP, but you don't need to implement this
> pattern with an abstract class. That's just there because you want
> common behavior. So how do you implement this pattern in Ruby?
>
> class AmericanCoffeeShop
> def make_coffee
> Coffee.new :ingredients => [ :water, :mud ]
> end
> end
>
> class ItalianCoffeeShop
> def make_coffee
> Espresso.new
> end
> end
>
> Simple, you've implemented the factory method pattern. We have an
> interface - make_coffee - and each class can instantiate an object of
> whatever kind it wants.
>
> If some client code needs to have a coffee made, you can just pass it
> an instance of either of those classes and it'll run fine.
>
> Shared behavior can be provided by a mixin (whereas in Java you need a
> superclass).
>
> module CoffeeProvider
> def order
> take_payment
> give_change
> make_coffee
> end
> end
>
> class AmericanCoffeeShop
> include CoffeeProvider
>
> def make_coffee
> Coffee.new :ingredients => [ :water, :mud ]
> end
> end
>
> class ItalianCoffeeShop
> include CoffeeProvider
>
> def make_coffee
> Espresso.new
> end
> end
>
> Now we've achieved the desired behavior. We've defined the high-level
> behavior of taking an order, but placed the responsibility on
> lower-level implementation details in another class. Now anyone can
> come along and write a class that knows how to provide an order of
> coffee, all without any foresight from the initial author of
> CoffeeProvider.
>
> Pat
>

Thanks a lot for the input!

Do you mind if I post your answer in Ruby Patterns? http://
www.rubypatterns.org


Pat Maddox

5/10/2007 7:30:00 AM

0

On 5/10/07, Enrique Comba Riepenhausen <ecomba@mac.com> wrote:
> Hey Pat!
>
> On 10 May 2007, at 09:16, Pat Maddox wrote:
>
> >
> > One clue is that the example is coded in Java, vs smalltalk. The
> > reason for that is that Smalltalk doesn't really have the problem
> > they're solving here. An "interface" is just going to be a bunch of
> > methods with the same method names and signatures.
> >
> > I'm sure they discusss it in DP, but you don't need to implement this
> > pattern with an abstract class. That's just there because you want
> > common behavior. So how do you implement this pattern in Ruby?
> >
> > class AmericanCoffeeShop
> > def make_coffee
> > Coffee.new :ingredients => [ :water, :mud ]
> > end
> > end
> >
> > class ItalianCoffeeShop
> > def make_coffee
> > Espresso.new
> > end
> > end
> >
> > Simple, you've implemented the factory method pattern. We have an
> > interface - make_coffee - and each class can instantiate an object of
> > whatever kind it wants.
> >
> > If some client code needs to have a coffee made, you can just pass it
> > an instance of either of those classes and it'll run fine.
> >
> > Shared behavior can be provided by a mixin (whereas in Java you need a
> > superclass).
> >
> > module CoffeeProvider
> > def order
> > take_payment
> > give_change
> > make_coffee
> > end
> > end
> >
> > class AmericanCoffeeShop
> > include CoffeeProvider
> >
> > def make_coffee
> > Coffee.new :ingredients => [ :water, :mud ]
> > end
> > end
> >
> > class ItalianCoffeeShop
> > include CoffeeProvider
> >
> > def make_coffee
> > Espresso.new
> > end
> > end
> >
> > Now we've achieved the desired behavior. We've defined the high-level
> > behavior of taking an order, but placed the responsibility on
> > lower-level implementation details in another class. Now anyone can
> > come along and write a class that knows how to provide an order of
> > coffee, all without any foresight from the initial author of
> > CoffeeProvider.
> >
> > Pat
> >
>
> Thanks a lot for the input!
>
> Do you mind if I post your answer in Ruby Patterns? http://
> www.rubypatterns.org
>
>
>

Go for it.

Pst

Enrique Comba Riepenhausen

5/10/2007 8:05:00 AM

0


On 10 May 2007, at 09:30, Pat Maddox wrote:

> On 5/10/07, Enrique Comba Riepenhausen <ecomba@mac.com> wrote:
>> Hey Pat!
>>
>> On 10 May 2007, at 09:16, Pat Maddox wrote:
>>
>> >
>> > One clue is that the example is coded in Java, vs smalltalk. The
>> > reason for that is that Smalltalk doesn't really have the problem
>> > they're solving here. An "interface" is just going to be a
>> bunch of
>> > methods with the same method names and signatures.
>> >
>> > I'm sure they discusss it in DP, but you don't need to implement
>> this
>> > pattern with an abstract class. That's just there because you want
>> > common behavior. So how do you implement this pattern in Ruby?
>> >
>> > class AmericanCoffeeShop
>> > def make_coffee
>> > Coffee.new :ingredients => [ :water, :mud ]
>> > end
>> > end
>> >
>> > class ItalianCoffeeShop
>> > def make_coffee
>> > Espresso.new
>> > end
>> > end
>> >
>> > Simple, you've implemented the factory method pattern. We have an
>> > interface - make_coffee - and each class can instantiate an
>> object of
>> > whatever kind it wants.
>> >
>> > If some client code needs to have a coffee made, you can just
>> pass it
>> > an instance of either of those classes and it'll run fine.
>> >
>> > Shared behavior can be provided by a mixin (whereas in Java you
>> need a
>> > superclass).
>> >
>> > module CoffeeProvider
>> > def order
>> > take_payment
>> > give_change
>> > make_coffee
>> > end
>> > end
>> >
>> > class AmericanCoffeeShop
>> > include CoffeeProvider
>> >
>> > def make_coffee
>> > Coffee.new :ingredients => [ :water, :mud ]
>> > end
>> > end
>> >
>> > class ItalianCoffeeShop
>> > include CoffeeProvider
>> >
>> > def make_coffee
>> > Espresso.new
>> > end
>> > end
>> >
>> > Now we've achieved the desired behavior. We've defined the high-
>> level
>> > behavior of taking an order, but placed the responsibility on
>> > lower-level implementation details in another class. Now anyone
>> can
>> > come along and write a class that knows how to provide an order of
>> > coffee, all without any foresight from the initial author of
>> > CoffeeProvider.
>> >
>> > Pat
>> >
>>
>> Thanks a lot for the input!
>>
>> Do you mind if I post your answer in Ruby Patterns? http://
>> www.rubypatterns.org
>>
>>
>>
>
> Go for it.

Done ;) http://www.rubypatterns.org...
gang_of_four_patterns:factory_method

>
> Pst
>