Joel VanderWerf wrote:
> Jamis Buck wrote:

>>   reg.define do |b|
>>     b.printer do |ctr,info|
>>       logger = ctr[:logs].get( info )
>>       lambda { |kind| Printer.new( logger, kind ) }
>>     end
>>
>>     b.code_printer { |ctr,| ctr.printer.call( :monochrome ) }
>>     b.image_printer { |ctr,| ctr.printer.call( :color ) }
>>   end
>>
>> I've actually incorporated this approach into various places in the 
>> upcoming new release of Net::SSH, and it works beautifully.
> 
> 
> That captures the parameterization, but it doesn't capture the 
> multiton[1] service model of my code. A unique instance is generated for 
> each distinct argument list (distinct in the sense of hash keys, which 
> is to say #eql?). What's the most natural way to do that with Needle?

Actually, the example does--I just enforced the singleton (multiton?) 
constraint in the code_printer and image_printer services. The +printer+ 
service itself, though, will generate a new instance for each invocation.

However, you could also create a service factory. It would do just as 
you did, with a Hash for caching created instances.

   class Printer
     def self.get( name )
       @printers ||= Hash.new
       @printers[ name ] ||= new( name )
     end

     private_class_method :new
     def initialize( name )
       ...
     end
   end

   reg.define.printers { Printer }

   p1 = reg.printers.get( :monochrome )
   p2 = reg.printers.get( :monochrome )
   assert_same p1, p2

In fact, this is almost exactly how the log-factory service in Needle 
works, although the LogFactory is a distinct class from the Logger.

I'm still thinking through how to implement something like this in 
Needle itself. It'll probably wind up being, as you suggested, a 
pipeline element of some sort, although the parameterization issue goes 
a bit deeper.

- Jamis

-- 
Jamis Buck
jgb3 / email.byu.edu
http://www.jamisbuck.org/jamis