The Flyweight design pattern is a memory consumption optimization technique. It reduces the amount of required memory by sharing the common and immutable state across many objects. Think about graphics rendering, if you have 10 different images and you want to draw them 50 times in different places on the screen, does it make sense to load the PNG file 500 times? Instead, you would want to load each individual PNG file only once and then reuse each loaded PNG file to draw them in a different place on the screen. This would result in having 10 different files loaded to the memory, and then those loaded files are reused to draw them on the screen in 50 different places. Effectively, instead of having 500 loaded images, we have only 10 loaded images which are reused 50 times.
The Flyweight design pattern divides the object state into two parts:
- Intrinsic state – common, shared, constant, immutable, read-only state – for example, a bitmap that can be reused to draw images in different parts of the screen
- Extrinsic state – unique, non-shared, mutable state – for example location on the screen
The idea here is to keep data that consumes a lot of memory in the Intrinsic state part and data that does not take a lot of memory in the Extrinsic state.
In the above example, bitmap usually consumes a lot of data and is immutable, so we keep it in an Intrinsic state. The location on the screen is just two integers, which are usually mutable (object can be moved) and do not take a lot of data. The object that keeps the Extrinsic state (location on the screen) uses then the object that keeps the Intrinsic state (bitmap) to draw the image on different parts of the screen.
The object that will store the Intrinsic state will be called a flyweight. Flyweight will be created by a FlyweightFactory, which will act as a caching factory i.e.: we avoid creating the same object multiple times. In the above example, it would mean avoiding loading the same image file multiple times.
The object that will store the Extrinsic state will be called the Context.
Joining the Intrinsic and Extrinsic states will give us a full state.
This pattern is especially useful in situations where memory usage is a concern, such as in resource-intensive applications like graphics rendering, game engines, or when operating in resource-constrained environments like mobile devices.
To read more on this and the other patterns, get “GoF Design Patterns Distilled” book from Amazon or Leanpub: