i did this so many times i decided to put it in one place.  i've found
it to be more usefull that true singletons - which it can still be
used as.

----CUT----
# Multiton module that ensures only one object to be allocated for a
given
# argument list.
#
# The 'multiton' pattern is similar to that of singleton. instead of
only one
# instance, there are several similar instances.  it's usefull when
you want to
# avoid constructing objects many times because of some huge expence
(connecting
# to a database for example), require a set of similar but not
identical
# objects, and cannot easily control how many time a contructor may be
called.
#
# Usage:
# class SomeMultitonClass
#   include Multiton
#   attr :arg
#   def initialize(arg)
#     @arg = arg
#   end
# end
#
# a = SomeMultitonClass.instance(4)
# b = SomeMultitonClass.instance(4)	# a and b are same object
# c = SomeMultitonClass.instance(2)     # c is a different object
#
# print([a.arg,b.arg].max, c.arg, "\n")
#
# a = SomeMultitonClass.new		# error (`new' is private)

module Multiton
  def Multiton.append_features(klass)
    klass.private_class_method(:new)
    klass.instance_eval <<-CODE 
      @__instances__ = {} 
      def instance(*args)
	__instance__ = @__instances__[args]
	unless __instance__
	  Thread.critical = true
	  begin
	    __instance__ = (@__instances__[args] = new(*args))
	  ensure
	    Thread.critical = false
	  end
	end
	return __instance__
      end
    CODE
  end
end

if __FILE__ == $0
  class SomeMultitonClass
    include Multiton
    attr :arg
    def initialize(arg)
      @arg = arg
    end
  end

  a = SomeMultitonClass.instance(4)
  b = SomeMultitonClass.instance(4)	# a and b are same object
  c = SomeMultitonClass.instance(2)     # c is a different object

  print([a.arg,b.arg].max, c.arg, "\n")

  a = SomeMultitonClass.new		# error (`new' is private)
end
----CUT----

-a

ahoward / fsl.noaa.gov (email down for a few days)