DESCRIPTION

A million tiny objects can weigh a ton.

Instead of creating a multitude of identical copies of objects, a flyweight is a memoized instance that may be reused in multiple contexts simultaneously to minimize memory usage. And due to the cost of constructing objects the reuse of flyweights has the potential to speed up your code.

MooseX::Role::Flyweight is a Moose role that enables your Moose class to automatically manage a cache of reusable instances. In other words, the class becomes its own flyweight factory.

Flyweight v. Singleton

MooseX::Role::Flyweight provides an instance() method which looks similar to MooseX::Singleton. This is in part because MooseX::Role::Flyweight departs from the original "Gang of Four" design pattern in that the role of the Flyweight Factory has been merged into the Flyweight class itself. But the choice of the method name was based on MooseX::Singleton.

While MooseX::Role::Flyweight and MooseX::Singleton look similar, understanding their intentions will highlight their differences:

Singleton

MooseX::Singleton limits the number of instances allowed for that class to ONE. For this reason, its instance() method does not accept construction arguments and will always return the same instance. If arguments are required for construction, then you will need to call its initialize() method.

Flyweight

MooseX::Role::Flyweight is used to facilitate the reuse of objects to reduce the cost of having many instances. The number of instances created will be reduced, but it does not set a limit on how many instances are allowed. Its instance() method does accept construction arguments because it is responsible for managing the construction of new instances when it finds that it cannot reuse an existing one.

METHODS

instance

$instance = My::Flyweight->instance( %init_args );

This class method returns an instance that has been constructed from the given arguments. The first time it is called with a given set of arguments it will construct the object and cache it. On subsequent calls with the equivalent set of arguments it will reuse the existing object by retrieving it from the cache.

The arguments may be in any form that new() will accept. This is normally a hash or hash reference of named parameters. Non-hash(ref) arguments are also possible if you have defined your own BUILDARGS class method to handle them (see Moose::Manual::Construction).

Note that instances that are constructed by calling new() directly do not get cached and therefore will never be returned by this method.

normalizer

This class method generates the keys used by instance() to identify objects for storage and retrieval in the cache. It is passed the arguments used for construction as a hashref (after they have passed through BUILDARGS). It returns a string representation of those arguments as the key. Equivalent arguments should result in the same string.

Note that this does not handle blessed references as arguments.

Generally you should not need to access this method directly. The only reason you would want to know about this method is if you want to change the way it generates the cache keys, in which case you should wrap or override this method in your class that consumes this role.

NOTES ON USAGE

Flyweights should be immutable

Your flyweight object attributes should be read-only. It is dangerous to have mutable flyweight objects because it means you may get something you don't expect when you retrieve it from the cache the next time.

Garbage collection of cached objects

The cache uses weak references to the objects so that the cache references do not prevent the objects from being garbage collected. This means that an object in the cache will be destroyed when all other references to it go out of scope.

my $obj = My::Flyweight->instance(%args);
# $obj is in the cache
undef $obj;
# $obj is garbage collected and disappears from the cache

AUTHOR

Steven Lee <stevenwh.lee@gmail.com>

ACKNOWLEDGEMENTS

Thanks to Mark Stosberg (MARKSTOS) for suggesting to explain the difference between MooseX::Role::Flyweight and MooseX::Singleton.