On Tue, 26 Jul 2005, Joe Van Dyk wrote:

> On 7/25/05, Ara.T.Howard <Ara.T.Howard / noaa.gov> wrote:
>> On Tue, 26 Jul 2005, Lyndon Samson wrote:
>>
>>> Factory is a very common pattern in the java world, in some places
>>> it's almost considered 'Evil (TM)' to have any sort of knowledge of
>>> object construction.
>>>
>>> In the Ruby world, where Classes and Objects seem to be de-emphasised,
>>> constructing an object with .new doesn't seem to be held as such a bad
>>> thing.
>>>
>>> I know there are a few IOC containers in the RubyWorld, but they dont
>>> seem to be overly popular.
>>>
>>> Why might this be so?
>>
>> probably because 'new' is a method and really doesn't give any clue as to how
>> an object is contructed - this is how i generally implement factory
>>
>>    class Factory
>>      class TypeA; end
>>      class TypeB; end
>>      class TypeC; end
>>
>>      def Factory::new(arg, *a, &b)
>>        klass =
>>          case arg
>>            when /a/
>>              TypeA
>>            when /b/
>>              TypeB
>>            when /b/
>>              TypeC
>>          end
>>        klass::new(*a, &b)
>>      end
>>    end
>>
>> although the returned type might depend on file extension or something else.
>> since 'new' is just a method on a class object it's always free to return
>> anything it likes.  the nice thing about this is that, in ruby, __every__ call
>> to new is, by definition, the factory pattern - it just so happens that there
>> is a default implementation inherited by class 'Class'.  simplicity.
>
>
> Would you mind giving an example of how you'd use that class?  How
> does it benefit the programmer?

well, __that__ class isn't useful to anyone ;-)  but if you have something
like this perhaps

   class JobRunner
     class AbstractJobRunner
       def initialize job
         @job = job
         @logger = Logger::new
       end
       def run
         @job.run 'logger' => @logger
       end
       def download_input src, dst
         raise NotImplementedError
       end
       def upload_output src, dst
         raise NotImplementedError
       end
     end
     class FTPJobRunner < AbstractJobRunner
       def download_input src, dst
         ...
       end
       def upload_output src, dst
         ...
       end
     end
     class HTTPJobRunner < AbstractJobRunner
       def download_input src, dst
         ...
       end
       def upload_output src, dst
         ...
       end
     end
     class SCPJobRunner < AbstractJobRunner
       def download_input src, dst
         ...
       end
       def upload_output src, dst
         ...
       end
     end
     class << self
       def new job
         klass =
           case job.input
             when %r|^ftp://|
               FTPJobRunner
             when %r|^scp://|
               SCPJobRunner
             when %r|^http://|
               HTTPJobRunner
           end
         klass::new job
       end
     end
   end

   class Job
     def initialize command, input, output
       ...
     end
   end

then all over your code just reads

   job_runner = JobRunner::new job
   job_runner.run

and you don't really care what kind of JobRunner it is... if this stuff were
in a library, and more kinds of JobRunners are later added, client code need
not change.  of course there are about a million ways to do this in ruby, but
an object factory is nice wherever your code needs an object that does 'x'
based on 'y' - you can encapsulate that logic and, later, change it only in
one place with a factory.  the built-in uri class does something similar:

   jib:~/eg/ruby > irb -r uri
   irb(main):001:0> URI::parse 'http://foobar'
   => #<URI::HTTP:0x..fdba9cc00 URL:http://foobar>

   irb(main):002:0> URI::parse 'ftp://foobar'
   => #<URI::FTP:0x..fdba9bc06 URL:ftp://foobar>

   irb(main):003:0> URI::parse 'scp://foobar'
   => #<URI::Generic:0x..fdba9ac16 URL:scp://foobar>

of course it's using 'parse' instead of 'new' - but the idea is the same.  you
just want a url-type object, but you don't really care what kind of object it
is so long as it supports some set of methods you'll be using later - nice with
duck typing ;-)

hth.

-a
-- 
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| My religion is very simple.  My religion is kindness.
| --Tenzin Gyatso
===============================================================================