implemented in the same way as the InstanceFlyweightPattern, but used for the opposite purpose.
- Name: ReverseFlyweightPattern
- Also Known As: MultitonPattern, n-ton pattern.
- Classification: CreationalPattern?? (because its usage is more like Singleton than Flyweight...)
- Motivation (of creating):
- Differentiation of the FlyweightPattern usage (where the instances/identities are not important, only the immutable state is) from this type of usage (where the instances are important, and the state is mutable).
- Generalizing the SingletonPattern to support multiple instances.
- Application:
Anywhere one wishes to save memory in creating objects that map to real world structures, for example IO ports on an embedded system. Additionally, the
ReverseFlyweightPattern allows the encapsulation of various fixed numbers, especially those fixed in hardware. A concrete example would be for objects representing computer monitors: the number of monitors is fixed at runtime, but can change between different computers, or even different runs of the same compiled instance of the program (or, with sufficiently
PlugAndPlay monitors, possibly even
while the program is running), so Singleton is
clearly not appropriate.
Alternatives are:
- instantiating an object for every action that needs that particular real-world structure; this is costly and assumes that all data is actually stored in said real-world structure.
- instantiating global objects for every real-world structure that the program might ever need at the beginning of each program/in a header file; there is no guarantee that any of these global objects will be used, wasting memory.
- Using global flags to do the ReverseFlyweightPattern by hand; this violates OnceAndOnlyOnce, because you have to do the "exists-yet?" check at every usage.
Also, because the
ReverseFlyweightPattern maps so closely over the
SingletonPattern, one can use it to replace the singleton.
- Structure: ?
- Participants: ?
- Collaborations: ?
- Consequences: Decreased memory usage as a result of less instantiated objects.
- Implementation: Same as the instance flyweight pattern. In perl, for example, it would be package Whatever; require 'memoize'; memoize 'new';
- Sample Code (written in PerlSix-like pseudocode)
#An embedded system has a certain number of IO pins, and each IOpin object maps to.
#The state of each IOpin object for any single given pin number is exactly the same.
#Essentially, this is an extension of the Singleton...
class IOpin extends SystemObject?
has(@address)
{
static Hashtable<Int, IOpin> cache;
static def getInstance(Int pinNumber)
{
IOpin _pin = null;
if (!cache.has(pinNumber)) {
_pin = new IOpin(pinNumber);
cache.set(pinNumber, _pin);
} else {
_pin = cache.get(pinNumber);
}
return _pin;
}
private def Initialize(Int pinNumber)
{
Pinlookup p = Pinlookup.getInstance();
@address = p.getPinAddress(pinNumber)
}
def pinstate()
{
lvalue(
set => def (Bool value) {
Memory m = Memory.getInstance(); #get singleton
m.poke(@address, value); #extern "C" { *(this->address) = value }
return value
},
get => def () {
Memory m = Memory.getInstance();
return m.peek(@address) #extern "C" { return *(this->address) }
}
)
}
}
Of course, this example doesn't HAVE to be a Reverse Flyweight, but this is the basic idea.
**
"An example is worth 1000 words..."
In this case, no. It tells me nothing. PatternForm would be appreciated.
OK, PatternForm has been added (GoF style), but some things are missing. Please help!
Much better, even in incomplete form.
CategoryPattern