There are situations where you create a large number of objects for your application. Using that many objects for a program might eat up a lot of memory space in the computer's RAM. This could certainly cause problems like the computer being slow, or worse the application crashing from time to time. To work around this particular problem, you can use a structural design pattern called flyweight.
What is a flyweight?
Flyweight is a structural design pattern that allows you to use the same elements in different contexts to lower RAM usage. This pattern is used when developers work with large applications that consist of huge amounts of objects. Flyweight could be used when code has many similar objects, and you can extract common parts from them.
This pattern's purpose is to store common parts of multiple objects in a single class instead of keeping data inside of each object.
Flyweight's example
Let's look at an example of flyweight in videogame code.
In our game, we have a large number of identical elements. These objects are placed all around the game world and they are the same object with a few tweaks. In this example, we'll look at trees. Our tree is a set of textures for leaves and trunk, polygon mesh, and a position on the map.
Without flyweight, we would have to define all of these attributes in each object. This way, we will have many similar tree objects whose attributes are the same. Their count can go up to hundreds or even thousands. Running the game with this code will rapidly take up all the available RAM.
But the only changing attribute in this situation is a tree's position on a map. All the other attributes are the same and could be shared between trees. So, we can extract these attributes from objects and place them into a new Model object.
This way, we will have only one instance of Model that will be used by all trees on the map.
Flyweight in pseudocode
Flyweight, as a class, contains all portions of original objects that could be shared. So, in this case, our flyweight is a Model class. It consists of a mesh, textures for the trunk, and leaves. You can look at Mesh, Trunk, Leaves as reference fields. They are stored somewhere, but you cannot change them inside a flyweight. You just point out their location, and if they exist, your code will work.
class Model is
Mesh mesh
Texture trunk
Texture leaves
constructor of Model(mesh, trunk, leaves) is ...
Usually, an implementation of flyweight includes the factory class that enables us to work with the flyweight class with different parameters, or to decide whether it is necessary to create a flyweight with a new set of parameters. So, in factory class, we will have a number of these classes, which were created using Model class.
class Factory is
List(Model) models;
method getModel(mesh, trunk, leaves) is
model = models.contains(mesh, trunk, leaves)
if(model == null)
model = new Model(mesh, trunk, leaves)
models.add(model)
return model
As we established earlier, this instance of a flyweight can be used in a different context. Classes that allow you to do that are called context classes. In our case, let's name it Tree. It will help us define different positions of trees.
class Tree is
Float x
Float y
Model treeModel
constructor of Tree(x, y, treeModel) is ...Flyweight in client code
Now we can use this model of trees in client code.
method RenderTree(x, y, mesh, trunk, leaves) is
treeModel = Factory.getModel(mesh,trunk,leaves)
tree = new Tree(x, y, treeModel)
As you can see, we instantiate Tree with just a few parameters; two coordinates and a referred model, which we check through a factory. The gist of this action is simple. Instead of making many instances with a lot of parameters, like textures and mesh every time, we can create one instance and copy it in different coordinates. After all, it's easier to work with two numbers instead of the whole geometry of a tree.
But do not forget that this pattern could make things more complex. And eventually, with an increasing amount of calculation needed, you will run into troubles on the CPU side, instead of RAM.
Conclusion
In conclusion, let's sum up the flyweight pattern:
- It is used to save memory space in the computer's RAM, by reusing common parts of objects.
- You should use it when you can extract duplicate parameters outside of the original objects.
- With it, you can create a large number of objects which share some common attributes through a flyweight class.
So, when you work with a big application and need to save some RAM, this is a pretty good way to do it. But be careful, as it can take up too much CPU power.