Module: Multiton
- Included in:
- Infinity
- Defined in:
- lib/mega/multiton.rb
Overview
:title: Multiton
Multiton module that ensures only one object to be allocated for a given argument list.
The ‘multiton’ pattern is similar to a singleton, but 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.
Synopsis
require 'carat/multiton'
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
In previous versions the Class.new method was made private, but for Semi Multitons this restriction has been lifted with the following caveat: Class.instance will attempt to retreive a previously cached object, constructing one if needed, but Class.new will always construct a new object - this should allow great flexiblity with multiton classes.
How It Works
We try to use a previously cached object, if one is not found we construct one and cache it in the pool based on class and the args given to the contructor
note: a limitation of this approach is that it is impossible to detect if different blocks were given to a contructor (if it takes a block. Thus, it is the constructor *args exclusively which determine the uniqueness of an object. A workaround is for the class to define the class method multiton_id, eg:
def Klass.multiton_id(*args, &block)
# ...
end
Which should return a hash key used to identify the object being constructed as (not) unique.
Author(s)
-
Thomas Sawyer
Defined Under Namespace
Constant Summary collapse
- POOLS =
pools of objects cached on class type
{}
- MULTITON_ID_HOOK =
method which can be defined by a class to determine object uniqueness
:multiton_id
- MULTITON_NEW_HOOK =
method which can be defined by a class to create multiton objects
:multiton_new
Class Method Summary collapse
Class Method Details
.append_features(klass) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/mega/multiton.rb', line 93 def self.append_features(klass) klass.private_class_method(:new) def klass.instance(*args, &block) # if the class defined 'multiton_id' we use this as the key # otherwise we simply use the argument list. k = (respond_to?(MULTITON_ID_HOOK) ? send(MULTITON_ID_HOOK, *args, &block) : args) unless (obj = (POOLS[self] ||= {})[k]) begin critical = Thread.critical Thread.critical = true meth = self.respond_to?(MULTITON_NEW_HOOK) ? MULTITON_NEW_HOOK : :new obj = (POOLS[self][k] = self.send(meth, *args, &block)) ensure Thread.critical = critical # restore state end end return obj end end |