Featured image of post SP6 - Object Pool - Learn Design Pattern From Simple Things

SP6 - Object Pool - Learn Design Pattern From Simple Things

Producing planes on a large scale is expensive, but fortunately the manufactured raw parts are always stored in the pool, thereby reducing duplication in the production process.

Object Pool (Flyweight) is a Structural design pattern: šŸ–¤šŸ–¤šŸ–¤šŸ¤šŸ¤

What is Object Pool?

Object Pool is a design pattern that reduces the memory usage and improves the performance of a system by sharing common objects instead of creating new ones. The shared objects are called Object Pools, and they can be reused by different contexts without modifying their internal state. The Object Pools only store the intrinsic state (the data that is shared by all the instances of the same type), while the extrinsic state (the data that is specific to each instance) is passed as a parameter to the Object Pool methods.

Imagine you are a plane factory owner who manages the properties of all plane models. The number of plane objects is increasing every day because of the demand for different models and colors! How can you optimize your system to avoid wasting memory and resources?

Object Pool diagram

Why use Object Pool?

Object Pool is a useful pattern when you have to deal with a large number of similar objects that consume a lot of memory. By sharing the common objects, you can reduce the memory footprint and improve the performance of your system. Object Pool also allows you to separate the intrinsic and extrinsic state of the objects, which makes them more flexible and adaptable to different contexts.

Advantages:

  • Reduces the memory usage by sharing common objects
  • Improves the performance by avoiding creating new objects
  • Separates the intrinsic and extrinsic state of the objects

Disadvantages:

  • Increases the complexity of the code by introducing a new layer of abstraction
  • Requires careful management of the shared objects and their states
  • May introduce bugs if the shared objects are not immutable

Question: I hate the Object Pool, what are the alternatives?

Answer: A simpler solution is to create new objects for each context, but this may result in high memory consumption and poor performance.

Object Pool

When to use Object Pool?

Question: When should I use Object Pool?

Answer: You should use Object Pool when you have to deal with a large number of similar objects that consume a lot of memory, and you can extract their common state and behavior.

Input:

You have two classes: Plane and PlaneFactory. The Plane class represents a plane object with one method get_flight_distance and two attributes: model, color. The PlaneFactory class acts as an Object Pool factory that creates and manages the Plane objects.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Plane:
    def __init__(self, model, color):
        self.model = model
        self.color = color

    def get_flight_distance(self, speed, time):
        flight_distance = speed * time
        return flight_distance


class PlaneFactory:
    def __init__(self):
        self.color = {"Boeing 747": "white", "Airbus A380": "blue"}

    def get_plane(self, model):
        color = self.color.get(model, "gray")
        plane = Plane(model, color)
        return plane

Expected Output:

You want to optimize your system by using the Object Pool design pattern. You want to separate the intrinsic state (the model) and the extrinsic state (the color) of the Plane objects. You want to store only one plane object for each model in the pool, and pass the color as a parameter to the plane methods. You want to reduce the memory usage and improve the performance of your system.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Create planes
# white_plane = factory.get_plane("Boeing 747")
# blue_plane = factory.get_plane("Airbus A380")
# another_white_plane = factory.get_plane("Boeing 747")
# print(white_plane is another_white_plane)
True

# Get the color for each plane
white
blue

# Get the distance for each plane
8000
10800

How to implement Object Pool?

Non-Object Pool implementation:

The non-Object Pool implementation creates new plane objects for each context, even if they have the same model. This results in high memory consumption and poor performance.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Plane:
    def __init__(self, model, color):
        self.model = model
        self.color = color

    def get_flight_distance(self, speed, time):
        flight_distance = speed * time
        return flight_distance


class PlaneFactory:
    def __init__(self):
        self.color = {"Boeing 747": "white", "Airbus A380": "blue"}

    def get_plane(self, model):
        color = self.color.get(model, "gray")
        plane = Plane(model, color)
        return plane


if __name__ == "__main__":
    factory = PlaneFactory()

    white_plane = factory.get_plane("Boeing 747")
    blue_plane = factory.get_plane("Airbus A380")
    another_white_plane = factory.get_plane("Boeing 747")
    print(white_plane is another_white_plane)
    print(white_plane.color)
    print(blue_plane.color)
    print(white_plane.get_flight_distance(800, 10))
    print(blue_plane.get_flight_distance(900, 12))

Object Pool Implementation:

The Object Pool implementation shares common plane objects instead of creating new ones. It separates the intrinsic state (the model) and the extrinsic state (the color) of the planes. It stores only one plane object for each model in the pool, and passes the color as a parameter to the plane methods. It reduces the memory usage and improves the performance of the system.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Plane:
    def __init__(self, model, color):
        self.model = model
        self.color = color

    def get_flight_distance(self, speed, time):
        flight_distance = speed * time
        return flight_distance


class PlaneFactory:
    def __init__(self):
        self.plane_pool = {}
        self.color = {"Boeing 747": "white", "Airbus A380": "blue"}

    def get_plane(self, model):
        if model not in self.plane_pool:
            color = self.color.get(model, "gray")
            plane = Plane(model, color)
            self.plane_pool[model] = plane
        else:
            plane = self.plane_pool[model]
        return plane


if __name__ == "__main__":
    factory = PlaneFactory()

    white_plane = factory.get_plane("Boeing 747")
    blue_plane = factory.get_plane("Airbus A380")
    another_white_plane = factory.get_plane("Boeing 747")
    print(white_plane is another_white_plane)
    print(white_plane.color)
    print(blue_plane.color)
    print(white_plane.get_flight_distance(800, 10))
    print(blue_plane.get_flight_distance(900, 12))

The code implements Object Pool design pattern by using two classes: Plane and PlaneFactory. The Plane class represents an Object Pool object that only stores its intrinsic state (the model). The PlaneFactory class acts as an Object Pool factory that creates and manages Plane objects. The factory has a dictionary called plane_pool that stores existing Plane objects by their model as key. The factory also has another dictionary called color that stores extrinsic state (the color) for each model. The factory has a method called get_plane that takes a model as parameter and returns a Plane object. If a Plane object of that model already exists in the pool, it returns it. Otherwise, it creates a new Plane object with the corresponding model and adds it to the pool. The Plane class has a method called get_color that takes a color as parameter and returns it. This way, the color is passed as an extrinsic state to the Plane objects, and can be different for each context.

This is how the code implements Object Pool design pattern by sharing common Plane objects instead of creating new ones. It separates the intrinsic and extrinsic state of the Plane objects, and reduces the memory usage and improves the performance of the system.

Object Pool is a useful design pattern when you have to deal with a large number of similar objects that consume a lot of memory. By sharing the common objects, you can optimize your system and make it more flexible and adaptable to different contexts.

Source Code

Made with the laziness šŸ¦„
by a busy guy