Object-oriented systems have a reputation for being big and slow. To some extent, this is a result of early, not particularly well-optimized implementations.
Smalltalk, C++, and Java were all extremely slow in their early incarnations and produced multimegabyte executables for even simple
Hello World-like programs.
More sophisticated runtime environments and compiler optimizations have gone a long way toward removing the performance overhead associated with objects.
However, it is still the case that in practice, object-oriented programming does not always produce the fastest code possible.
If the objects in question are immutable (that is, they never change after they are constructed), and there are a relatively small number of states that the objects can assume, it may be possible to radically reduce the total number of objects in the
system by using only copies of a few preconstructed objects.
For example, a
Character
class for a word processor might have only 200 or so instances (the lower and uppercase letters, assorted punctuation marks, white space, digits, and a few others).
A 20,000-character document might simply contain a list of 20,000 pointers to the 200 individual objects rather than 20,000 separate objects.
If the pointers are much smaller or much faster to work with than the objects themselves (as they often are in practice) the memory footprint of a document can be reduced by a factor of 100 or more with a corresponding increase in performance.
The
Flyweight pattern does exactly this.
The Flyweight pattern describes how to share objects to allow their use at fine granularities without prohibitive cost. Each object of the flyweight pattern is divided into two pieces:
- the state-dependent (extrinsic) part, and
- the state-independent (intrinsic) part.
Intrinsic state is stored in the Flyweight object. Extrinsic state is stored or computed by client objects, and passed to the Flyweight when its operations are invoked.
FlyweightFactory: Creates and manages unique Flyweight objects Flyweight: Stores intrinsic state that is shareable among all objects There are other design options.
For example, in Figure 5-5 the Flyweight is shown as computing the extrinsicState.
However, the Client could do the computation and pass the extrinsicState to the Flyweight as a parameter to the Operation. Also, we regard the unSharedState as a Dictionary of values related to the Flyweights.
However, the unSharedState could have a more complex structure, warranting its own class. In this case, it would stand alongside the Flyweight class and implement the IFlyweight interface.