Multiton
¶ ↑
Multiton
is an implementation of the multiton pattern in pure Ruby. Some its features include:
-
Can be used to implement the singleton pattern in a very straightforwad way.
-
Transparent interface that makes designing multiton classes as easy as designing regular ones.
-
Support for serializing and deserializing multiton instances.
-
Clonning, duplicating and inheriting from a multiton class will create a new multiton class.
-
Thread safety, implemented via shared/exclusive locks.
Installation¶ ↑
Add this line to your application's Gemfile:
gem "ruby_multiton"
And then execute:
$ bundle
Or install it yourself as:
$ gem install ruby_multiton
Usage¶ ↑
Implementing a singleton class¶ ↑
The easiest use case for Multiton
is to implement a singleton class. To achieve this Multiton
mimics the approach used by the Singleton module from Ruby's standard library:
require "multiton" class C extend Multiton end C.instance.object_id #=> 47143710911900 C.instance.object_id #=> 47143710911900
As an example lets create a singleton object that returns the amount of seconds elapsed since it was first initialized:
class Timestamp extend Multiton def initialize self.initialized_at = Time.now end def elapsed_seconds Time.now - initialized_at end private attr_accessor :initialized_at end Timestamp.instance #=> #<Timestamp:0x00562e486384c8 @initialized_at=2017-04-17 20:00:15 +0000> # Some time later... Timestamp.instance.elapsed_seconds #=> 542.955918039
Implementing a multiton class¶ ↑
To implement a multiton class we will need a key
to be able to access the different instances afterwards. Multiton
achieves this by using the parameters passed to the initialize
method as the key
:
require "multiton" class C extend Multiton def initialize(key) end end C.instance(:one).object_id #=> 47387777147320 C.instance(:one).object_id #=> 47387777147320 C.instance(:two).object_id #=> 47387776632880 C.instance(:two).object_id #=> 47387776632880
As an example lets create multiton objects representing playing cards that we can check if they were drawn or not:
class Card extend Multiton def initialize(number, suit) self.has_been_drawn = false end def draw self.has_been_drawn = true end def drawn? has_been_drawn end private attr_accessor :has_been_drawn end Card.instance(10, :spades).drawn? #=> false Card.instance(5, :hearts).draw Card.instance(10, :spades).draw Card.instance(5, :hearts).drawn? #=> true Card.instance(10, :spades).drawn? #=> true Card.instance(2, :diamonds).drawn? #=> false
Serializing and deserializing multiton instances¶ ↑
Multiton
instances can be serialized and deserialized like regular objects. Continuing with the previous Card
example:
Card.instance(2, :diamonds).drawn? #=> false serialized_card = Marshal.dump(Card.instance(2, :diamonds)) Marshal.load(serialized_card).drawn? #=> false Card.instance(2, :diamonds).draw Marshal.load(serialized_card).drawn? #=> true
Clonning, duplicating and inheriting from multiton classes¶ ↑
Multiton
supports cloning, duplicating and inheriting from a multiton class:
require "multiton" class C extend Multiton end D = C.clone E = D.dup class F < E end F.instance.object_id #=> 47418482076880 F.instance.object_id #=> 47418482076880
Note that C
, D
, E
and F
are all considered different classes and will consequently not share any instances.
Contributing¶ ↑
-
Fork it ( github.com/gdeoliveira/ruby_multiton/fork )
-
Create your feature branch (
git checkout -b my-new-feature
) -
Commit your changes (
git commit -am "Add some feature"
) -
Push to the branch (
git push origin my-new-feature
) -
Create a new Pull Request