Avoid redundancy when storing data !
Or, as stated in GoF :
Use sharing to support large numbers of fine-grained objects efficiently.
To put it in a nutshell : Space optimization technique ;)
Note : The Flyweight is a shared object that can be used simultaneously in multiple contexts but the Client will not even be able to know that this object is shared in another context.
You should use the Flyweight pattern in the following cases :
- The naive approach (create as many objects as you need) would be prohibitively expensive.
- For example, using an object for each particle of a particles system or each character of a text editor probably would not fit into the available RAM.
- Your application should be able to support a large number of objects which barely fit into available RAM.
- You application contains objects with duplicate states that could be extracted and shared between multiple objects. (Extrinsic states)
- Your application does not depend on objects identity.
Participants
- Flyweight : Interface on which Flyweights act on extrinsic state.
- ConcreteFlyweight :
- Implements Flyweight interface.
- Declares the storage of intrinsic state if needed.
- Must be shareable and context-independent (i.e. the states it stores have to be context-independent).
- UnsharedConcreteFlyweight : For the Flyweight objects that do not need to be shared.
- FlyweightFactory :
- Creates and manages Flyweight objects.
- Control proper sharing between clients calls.
- Client :
- Maintains a reference to a Flyweight.
- Computes or stores the extrinsic state of Flyweights.
How to implement
- Separate the fields of the class to become a Flyweight
- Intrinsic states
- Contextual data unique to each object that cannot be shared.
- Extrinsic states
- Independents from context and shared by many objects
- To be removed from shared objects.
- Leave the fields that represent the intrinsic state in the class, but make sure they’re immutable. They should take their initial values only inside the constructor.
- You might consider creating a FlyweightFactory class to manage the pool of Flyweights (check for existence at Client calls and provide it with an existing or new Flyweight).
- You might consider moving the Flyweight referencing field of the Client as well as the extrinsic state to a separate context class.
Note : UML class diagram taken from here
Pros
- Memory : Save lots of RAM.
- Response time : Data caching is likely to improve the response time of your application.
- Centralize the managing mechanism of your objects states.
Cons
- Memory/CPU tradeoff
- Concurrency : In a concurrent environment, you might be ending up with multiples instances of the same Flyweight object. This problem can be eliminated using the Factory pattern such that Clients obtain flyweights from the FlyWeightFactory only.
- Provides no reliability on object identity
- The same physically created object represents many logically different objects.
- Therefore, applications that depend on object identity should not use flyweights.
Here are some usefull ressources :
- The w3sdesign is really clear and concise !
- A blog article
- A Refactoring guru article.