How to Implement the Flyweight Pattern in Python
Implements the Flyweight design pattern to share immutable intrinsic state (character + font) across many document objects, reducing memory usage.
Python code
51 linesclass Character:
"""Flyweight - stores only intrinsic state (shared)."""
def __init__(self, char: str, font: str):
self.char = char
self.font = font
def render(self, size: int) -> str:
return f"{self.char}_{self.font}_{size}"
class CharacterFactory:
"""Flyweight factory - manages shared instances."""
def __init__(self):
self._styles = {}
def get_character(self, char: str, font: str) -> Character:
key = (char, font)
if key not in self._styles:
self._styles[key] = Character(char, font)
return self._styles[key]
def count(self) -> int:
return len(self._styles)
def main():
factory = CharacterFactory()
document = [
factory.get_character("H", "Arial"),
factory.get_character("e", "Arial"),
factory.get_character("l", "Arial"),
factory.get_character("l", "Arial"),
factory.get_character("o", "Arial"),
factory.get_character("W", "Times"),
factory.get_character("o", "Times"),
factory.get_character("r", "Times"),
factory.get_character("l", "Times"),
factory.get_character("d", "Times"),
]
for ch in document:
print(ch.render(12))
print(f"\nUnique flyweights created: {factory.count()}")
if __name__ == "__main__":
main()
Output
H_Arial_12
e_Arial_12
l_Arial_12
l_Arial_12
o_Arial_12
W_Times_12
o_Times_12
r_Times_12
l_Times_12
d_Times_12
Unique flyweights created: 8
How it works
The Character class stores only intrinsic state — the character and its font — which is shared across all occurrences in the document. The CharacterFactory maintains a dictionary keyed by (char, font) tuples, guaranteeing that identical combinations return the same instance. The render method accepts extrinsic state (size) as a parameter, since that varies per usage and should not be stored in the flyweight. Every call to get_character with the same key reuses the cached object, so only 8 unique flyweights are created for a 10-character document instead of 10 objects. This pattern dramatically reduces memory when dealing with large numbers of similar objects.
Common mistakes
- Storing extrinsic state (like size or position) inside the flyweight object
- Creating new instances in the factory without checking the cache first
- Using mutable fields in flyweight objects, breaking shared-state invariants
Variations
- Use a module-level dictionary with `functools.lru_cache` on a factory function
- Store the flyweight registry in a class-level dict instead of an instance attribute
Real-world use cases
- Rendering large text documents in word processors where repeated characters share the same font style.
- Managing graphical sprites in game engines where the same image is reused thousands of times on screen.
- Caching database connection configurations or HTTP client presets to avoid redundant object creation.
Sponsored
More from System design patterns
- Build a BFF (Backend for Frontend) Mock Aggregator in Python medium
- Builder pattern for mocking complex objects in Python easy
- Circuit Breaker Pattern in Python: Closed, Open, and Half-Open States medium
- Create a Data Helper Class in Python easy
- Domain Driven Design Aggregate Root Example in Python medium
- Facade Pattern in Python with Mock Simplification medium
Keep learning
Related tutorials and quizzes for this topic.