Flyweight design pattern in python

This is one of the variations of the structural design patterns. This design pattern helps to minimize the total number of objects. When there is a need for similar types of objects, it makes a flyweight object that enables sharing without creating multiple objects. We can perform the necessary actions. It minimizes the use of memory by sharing similar objects. The flyweight object works and looks similar to the original object. It has no difference. Flyweight objects are immutable. This means once this object is created, then we cannot modify it. No further modification is allowed. We make use of a dictionary here. Objects are stored as keys so we can easily have reference to the created object, which makes the work simple. It takes low memory. Memory consumption is limited. This object can be used in multiple contexts. Normally this method tries to use an existing object rather than creating one if we require a large number of objects, so we can use this method to implement the programming logic. It reduces the number of objects. It reduces the amount of memory and storage devices required if the objects are persisted.

When we use the Flyweight design pattern,

  • We will use this method
  •  If there are many similar types of objects. If the number of objects is large, we will use this method.
  • If there is a concern about memory, we can use this method. We will be creating a few objects and sharing them simultaneously.

Types of flyweight design patterns:

Normally, there are two types of flyweight design patterns: intrinsic and extrinsic.

  • This is an intrinsic design pattern: it indicates that the property of data is similar in many objects.
  • Extrinsic design pattern: it indicates that the data's property is unique.

Problem statement :

Suppose you are a passionate developer and have been thinking of developing a video game for a long time. So finally, after one week, you decide to build a video game, and you decide on the theme of fighting soldiers. You started working on it. You added various types of bullets, tanks, airplanes, fighting equipment, etc. It took you two months to create the game, and finally, the day arrived when you committed your last push. The game is ready, so now you need to test it in all areas to determine whether it works properly. You sent the game to one of your friends, who installed it and started playing. He found it miserable because he could not play the game for long. The game kept crashing, and then he informed you about this problem. You thought it might be the problem with his phone, then you started playing the game, and you were facing the same problem. The game keeps crashing, so now you need to debug the code. You open the debug terminal and are trying to figure out what is wrong with the game. After searching, you finally decided that something was wrong with the lighting equipment. It is consuming RAM a lot, so the game keeps crashing. Then you realize that for each bullet fired, it is taking a different space in RAM. The main problem is with fighting equipment. Each piece of equipment, even separate bullets, consumes different memory on RAM. That's why it could not fit on the existing RAM. Some of you might think that now we will add RAM with more storage to our computer so that the game can be played but stop and think once. If I increase the RAM size, the user might play the game for a long time. Still, after a while, the game will crash too when the RAM is again consumed, so this is not a reliable solution, and the fact is that our game should adjust as per different RAM. We cannot change or increase the RAM for a specific game. We need to make our game less space-consuming, so now the question arises of how this can be done?

Solution statement :

You will not be updating your RAM, for sure. A flyweight pattern says to reuse existing similar kinds of objects by storing them and creating new objects when no matching object is found. Using a flyweight pattern will help us need to make flyweight objects of similar types of objects that enable sharing so that without creating multiple objects, we can perform the necessary actions. It minimizes the use of memory by sharing similar objects. We cannot minimize some objects, so we will not be doing anything about that. Still, multiple objects can be used as flyweights so we will do that. And this will help our game consume less RAM, and anybody can play the game for a long time, so the game will not crash anymore.

Example.py code:

class first_trucks(object): 
    #class for trucks
    def __init__(self): 
        pass
    def trucks(self, trucks_name): 
        return "Flyweightpattern[% s]" % (trucks_name) 
class trucksKingdom(object): 
    trucks_family = {}     #This stores ids of trucks
   def __new__(coll,name, trucks_family_ident): 
        try: 
            id = coll.trucks_family[trucks_family_ident] 
        except KeyError: 
            id = object.__new__(coll) 
            coll.trucks_family[trucks_family_ident] = id
        return id
    def put_trucks_info(self, trucks_info):
        #feed the  trucks info
       bc = first_trucks() 
        self.trucks_info = bc.trucks(trucks_info) 
    def get_trucks_info(self): 
        #return the available trucks info
        return (self.trucks_info) 
if __name__ == '__main__': 
 trucks_data = (('a', 1, 'Red'), ('a', 1, 'Yellow'), ('a', 1, 'Blur'), ('a',1,'Red')) 
trucks_family_objects = [] 
for i in trucks_data: 
        item = trucksKingdom(i[0], i[1]) 
        item.put_trucks_info(i[2]) 


trucks_family_objects.append(item)  
#If id same than they are having same objects
for j in trucks_family_objects: 
        print(" id = " + str(id(j))) 
        print(j.get_trucks_info())

Output.txt :

id = 140205127993488
Flyweightpattern[Red]

Explanation:

Flyweight design pattern in Python

[you can observe the basic structure and attributes of all the trucks will be the same there will be some differences in attributes such as color but their ability is the same, which means creating objects individually for color in each truck is not the best decision we can create a flyweight object for color and each truck will use it .]

Let's understand the workings of the code. Suppose this is the structure of a truck-loading game. Each truck object contains some of the same information. If we have created different objects for each truck, it may fill our RAM space very easily, and the game will crash. For a simple explanation, thinking of color and providing color to each object individually will consume more space, so we have created a flyweight object for similar data, which will help our truck game to work properly.

Creation of truck object :

class trucksKingdom(object): 
    trucks_family = {}     #This stores ids of trucks
    def __new__(coll,name, trucks_family_ident): 
        try: 
            id = coll.trucks_family[trucks_family_ident] 
      except KeyError: 
            id = object.__new__(coll) 
            coll.trucks_family[trucks_family_ident] = id
        return id

We are creating an object named truck kingdom, which will be creating ids, which will return the unique Id to each object.

Passing data to truck object :

 trucks_data = (('a', 1, 'Red'), ('a', 1, 'Yellow'), ('a', 1, 'Blue'), ('a',1,'Red'))

Printing object :

   item = trucksKingdom(i[0], i[1]) 
        item.put_trucks_info(i[2]) 

We provide the necessary data to the object, and then a flyweight object will be created. Lastly, we will be printing all the data.

So, by this example, we can see how we optimize the memory consumption, which will help the software work properly and boost its performance.

Advantages of flyweight design pattern :

  • This is a superior method to reduce memory consumption when there are so many similar objects, so making their flyweight objects is the best way t boost the performance of the software.
  • Creating flyweight object also reduces the total number of objects in the program. Suppose you have two classes, each of them contains two objects of color, so you have to make two objects, but if you use flyweight instead, then you need to create one flyweight object, and that can be used for both the objects, so you do not have to create objects individually. This is how the number of objects is reduced.
  • The catching and response time of the flyweight design pattern is comparatively fast, so if the user wants the program to respond quickly, then using the flyweight design pattern is the best way to do so.
  • The program's overall performance is improved by using the flyweight design pattern.

Disadvantages of flyweight design pattern :

  • The flyweight design pattern might have many advantages, but the main drawback is that its usability depends upon the programming language used. If you are using a high-level language such as Python, then it is easy to implement. Still, it isn't easy to implement in the case of c, c++, or c# (low-level languages) because the user's actions may destroy the objects.
  • The complication of the program increase, and the code might not be understandable for beginner programmers.
  • If we want to move outside of the object, then there is a big issue: we have to break encapsulation, which is not reliable.