Flyweight Pattern

Updated Nov 23, 2025

Flyweight Pattern

Intent:

Reduces memory usage by sharing common parts of objects. It's used when you need to create a large number of similar objects, and you want to minimize memory usage by sharing common state.

When to Use:

When you need to create many objects that share common data. Instead of storing this data in each object, you store it once and share it among all objects.

Key Characteristics:

  • Shares common state among many objects
  • Reduces memory usage significantly
  • Separates intrinsic (shared) state from extrinsic (unique) state
  • Useful when creating many similar objects

Think of it like bullets in a game - millions of bullets are fired, but they all share common properties (shape, material, damage). Only position and trajectory are unique to each bullet.


🎮 Example: Bullets in PUBG Game

Let's say we're building a game like PUBG where millions of bullets are fired. Each bullet has shared properties (type, damage, speed) and unique properties (position, direction). We'll use Flyweight to share common data.

Step 1: Define Flyweight Interface

# bullet_flyweight.py from abc import ABC, abstractmethod class BulletFlyweight(ABC): @abstractmethod def get_damage(self): pass # Returns bullet damage @abstractmethod def get_speed(self): pass # Returns bullet speed @abstractmethod def get_type(self): pass # Returns bullet type

Step 2: Create Concrete Flyweight (Shared State)

# bullet_type.py from bullet_flyweight import BulletFlyweight class BulletType(BulletFlyweight): """Flyweight - stores shared/intrinsic state""" def __init__(self, bullet_type, damage, speed): self._type = bullet_type self._damage = damage self._speed = speed def get_damage(self): return self._damage def get_speed(self): return self._speed def get_type(self): return self._type

Step 3: Create Flyweight Factory

# bullet_factory.py from bullet_type import BulletType class BulletFactory: """Factory to create and cache bullet types (flyweights)""" _bullet_types = {} # Cache for flyweights @classmethod def get_bullet_type(cls, bullet_type): """Get or create bullet type (flyweight)""" if bullet_type not in cls._bullet_types: # Create new bullet type based on type if bullet_type == "9mm": cls._bullet_types[bullet_type] = BulletType("9mm", 25, 400) elif bullet_type == "5.56mm": cls._bullet_types[bullet_type] = BulletType("5.56mm", 40, 900) elif bullet_type == "7.62mm": cls._bullet_types[bullet_type] = BulletType("7.62mm", 50, 750) elif bullet_type == "Shotgun": cls._bullet_types[bullet_type] = BulletType("Shotgun", 80, 300) else: cls._bullet_types[bullet_type] = BulletType(bullet_type, 30, 500) return cls._bullet_types[bullet_type] @classmethod def get_bullet_count(cls): """Get number of unique bullet types created""" return len(cls._bullet_types)

Step 4: Create Bullet Context (Unique State)

# bullet.py from bullet_factory import BulletFactory class Bullet: """Context - stores unique/extrinsic state""" def __init__(self, bullet_type, x, y, direction): # Shared state (flyweight) self.bullet_type = BulletFactory.get_bullet_type(bullet_type) # Unique state (extrinsic) self.x = x self.y = y self.direction = direction def fire(self): """Fire the bullet""" print(f"[PUBG Logo] Firing {self.bullet_type.get_type()} bullet") print(f" Position: ({self.x}, {self.y})") print(f" Direction: {self.direction}°") print(f" Damage: {self.bullet_type.get_damage()}") print(f" Speed: {self.bullet_type.get_speed()} m/s") def get_info(self): return f"{self.bullet_type.get_type()} at ({self.x}, {self.y})"

Step 5: Use the Flyweight (Client Code)

# main.py from bullet import Bullet from bullet_factory import BulletFactory # Simulate firing many bullets in the game print("=== PUBG Game - Firing Bullets ===\n") bullets = [] # Fire 1000 bullets of different types import random bullet_types = ["9mm", "5.56mm", "7.62mm", "Shotgun"] positions = [(random.randint(0, 1000), random.randint(0, 1000)) for _ in range(1000)] directions = [random.randint(0, 360) for _ in range(1000)] for i in range(1000): bullet_type = random.choice(bullet_types) x, y = positions[i] direction = directions[i] bullet = Bullet(bullet_type, x, y, direction) bullets.append(bullet) # Show first 5 bullets print("First 5 bullets fired:\n") for i in range(5): bullets[i].fire() print() # Show statistics print(f"\n=== Statistics ===") print(f"Total bullets fired: {len(bullets)}") print(f"Unique bullet types created: {BulletFactory.get_bullet_count()}") print(f"Memory saved: Instead of storing type data {len(bullets)} times,") print(f" we store it only {BulletFactory.get_bullet_count()} times!") print(f"Memory efficiency: {((1 - BulletFactory.get_bullet_count()/len(bullets)) * 100):.2f}% saved")

Output:

=== PUBG Game - Firing Bullets ===

First 5 bullets fired:

[PUBG Logo] Firing 5.56mm bullet
  Position: (234, 567)
  Direction: 45°
  Damage: 40
  Speed: 900 m/s

[PUBG Logo] Firing 9mm bullet
  Position: (123, 456)
  Direction: 90°
  Damage: 25
  Speed: 400 m/s

[PUBG Logo] Firing Shotgun bullet
  Position: (789, 012)
  Direction: 180°
  Damage: 80
  Speed: 300 m/s

[PUBG Logo] Firing 7.62mm bullet
  Position: (345, 678)
  Direction: 270°
  Damage: 50
  Speed: 750 m/s

[PUBG Logo] Firing 9mm bullet
  Position: (456, 789)
  Direction: 135°
  Damage: 25
  Speed: 400 m/s

=== Statistics ===
Total bullets fired: 1000
Unique bullet types created: 4
Memory saved: Instead of storing type data 1000 times,
              we store it only 4 times!
Memory efficiency: 99.60% saved

✅ Benefits

1. Memory Efficiency:

  • Shares common data among many objects
  • Significantly reduces memory usage
  • Critical for games and applications with many objects

2. Performance:

  • Less memory means faster execution
  • Better cache utilization
  • Reduced garbage collection

3. Scalability:

  • Can create millions of objects efficiently
  • Memory usage doesn't grow linearly with object count

4. Separation of Concerns:

  • Clear separation between shared and unique state
  • Easy to understand and maintain

🎯 Key Points

  • Flyweight shares common state among many objects
  • Separates intrinsic (shared) state from extrinsic (unique) state
  • Factory caches and reuses flyweight objects
  • Significant memory savings when creating many similar objects
  • Perfect for games, graphics, and applications with many objects

🌟 Quick Summary

  • Problem: Need to create many similar objects, but storing all data in each object wastes memory
  • Solution: Share common data (flyweight) and store only unique data in each object
  • Benefit: Massive memory savings when creating many similar objects
  • Example: PUBG bullets - millions of bullets share type/damage/speed, only position/direction are unique

🎉 End

The Flyweight Pattern helps you optimize memory usage when creating many similar objects. It's perfect for games, graphics applications, and any scenario where you need to create thousands or millions of objects!