The Flyweight Pattern
Use sharing to support large numbers of fine-grained objects efficiently.
Flyweight separated varying state from non-varying functionality, and encapsulates that state which allows the functionality to be reused.
Functions that can be called with different parameters, reusing their algorithms for multiple purposes.
An Air B&B can be rented to anyone. The living space is one thing, reused by many people, but each person brings along their own toiletries, medications, and other personal items.
Font systems model each letter with a different class that is capable of scaling, micro-positioning, kerning, and other, often heavyweight, behaviors. If a large document contains many examples of, say, the letter A, then creating an instance of A for each appearance would be wasteful since all A’s would behave the same; the only difference would be their location (row and column, for example). The Flyweight suggests pulling out the varying state position into lightweight objects, all of which defer to the single instance of the letter for all behaviors.
Questions, concerns, credibility checks
The Flyweight increases delegation in the system to reduce resource consumption, but does create more use of the stack, the VAT, and other virtualization resources of the runtime. Thus, we sacrifice a bit of performance to avoid wasting memory. The Flyweight can be used to eliminate any manner of client-specific state from coupling to any kind of behavior, thus whenever a heavyweight entity is created, the Flyweight should be considered as a possibility. A good example of this is the Façade. The Flyweight assumes that all reuse of the behavior object is consistent. If there are exceptions to this, an Adapter or Proxy can be used to resolve the differences. The behavior objects are often Singletons to enforce they are not created repeatedly.
Options in implementation
The behavioral object can be designed using any applicable design pattern. The flyweight itself is usually just a simple value object.
The Flyweight (CharPosition in the example) can easily be tested against a Mock of the behavioral object, making the test fast and narrowly focused.
The main benefit is avoiding re-building heavyweight object needlessly, thus improving system performance and throughput. the only cost is the additional delegation from the flyweight to the behavior, but this is easily outweighed by the gains in most cases.