Structural Patterns  «Prev  Next»
Lesson 5Flyweight: motivation
ObjectiveExplore the Motivations of the Flyweight Pattern

Flyweight Pattern and Motivation

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.

Flyweight Pattern

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:
  1. the state-dependent (extrinsic) part, and
  2. 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.

Figure 5-5: Flyweight Pattern Diagram consisting of 1) Client, 2) FlyweightFactory, 3) IFlyweight interface, 4)Flyweight class

The Flyweight pattern relies on being able to divide up the application’s state into four types.
  1. The intrinsicState resides in the Flyweight objects.
  2. The Flyweight class implements an IFlyweight interface, which specifies the operations upon which the rest of the system relies.
  3. The Client maintains the unSharedState as well as a dictionary of all the Flyweights, which it gets from a FlyweightFactory whose job it is to ensure that only one of each value is created.
  4. Finally, the extrinsicState does not appear in the system as such; it is meant to be computed at runtime for each instrinsicState instance, as required.

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.