Computer scienceFundamentalsEssentialsSoftware constructionDesign patternsStructural design patterns

Flyweight pattern

7 minutes read

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.

many similar tree objects with same attributes

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.

many similar tree objects with some common attributes extracted and shared

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.

8 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo