概要
Flyweight(フライウェイト)パターンは、
大量に生成される同一・類似オブジェクトの内部状態を共有化することで、
メモリ使用量と生成コストを最適化する設計手法である。
主に、ゲーム開発、テキストレンダリング、マップシステムなど、
「構造は異なるが構成要素が重複する」ようなケースで高い効果を発揮する。
1. なぜFlyweightが必要か?
❌ 大量の重複データを持つオブジェクトを都度生成
class Tree:
def __init__(self, type_name, texture, height):
self.type_name = type_name
self.texture = texture
self.height = height
→ 数千個のツリーが存在すると、テクスチャや種別情報が何度も複製されて非効率
✅ 共通部分(内部状態)を共有し、個別状態のみを保持
# TreeType: 共有される内部状態
# Tree: 個別の座標など外部状態を持つ
→ インスタンスの数を論理的に保ちつつ、実メモリを削減
2. 基本構造
✅ Flyweightクラス(内部状態)
class TreeType:
def __init__(self, name, color, texture):
self.name = name
self.color = color
self.texture = texture
def draw(self, x, y):
print(f"Draw [{self.name}] at ({x}, {y})")
✅ FactoryでFlyweightを管理
class TreeFactory:
_types = {}
@classmethod
def get_tree_type(cls, name, color, texture):
key = (name, color, texture)
if key not in cls._types:
cls._types[key] = TreeType(name, color, texture)
return cls._types[key]
✅ 個別オブジェクト(外部状態のみ)
class Tree:
def __init__(self, x, y, tree_type):
self.x = x
self.y = y
self.type = tree_type
def draw(self):
self.type.draw(self.x, self.y)
✅ 使用例:数千本の木を効率的に生成
forest = []
for i in range(10000):
ttype = TreeFactory.get_tree_type("Oak", "Green", "oak_texture.png")
forest.append(Tree(i % 100, i // 100, ttype))
forest[0].draw() # Draw [Oak] at (0, 0)
→ TreeType
は1つ、Tree
は10000個でも メモリ負荷を劇的に低減
3. Python的応用:文字オブジェクトの共有化
class CharFlyweight:
_pool = {}
@classmethod
def get(cls, char):
if char not in cls._pool:
cls._pool[char] = char
return cls._pool[char]
text = [CharFlyweight.get(c) for c in "hello world" * 1000]
→ 同一文字オブジェクトを共有することで、メモリ節約
4. 実務ユースケース
✅ テキストエディタでの文字レンダリング
→ フォントや文字ごとのスタイルを共有化し、軽量化
✅ ゲーム内オブジェクト(敵キャラ、背景、木々など)
→ 外見情報は共有し、位置・ライフなどは個別に管理
✅ マップ/地図情報の構造物パターンの最適化
→ 同一建物タイプなどを共有し、構造の再利用を促進
5. よくある誤用と対策
❌ 全てを共有して状態が干渉する
→ ✅ 外部状態(mutableな位置やスコアなど)は絶対に個別管理
❌ キャッシュが肥大化しメモリリーク
→ ✅ Factoryにキャッシュ上限や削除ルール(LRU)を実装
❌ Flyweightを意識しすぎて設計が複雑に
→ ✅ 共有メリットが明確な場面に限定し、オーバーエンジニアリングを回避
結語
Flyweightパターンとは、“無限に広がる構造を有限な部品で支える”設計戦略である。
- 重複した情報を構造的に共有し、メモリ効率とスケーラビリティを両立
- 表現は多様でも、本質的に「同じ」ものを共通化し、構成要素として再定義する
- Pythonにおいても、クラス設計とFactoryの工夫で柔軟かつ軽量な構造化が可能
Pythonicとは、“不要な重複を設計で消す”ことであり、
Flyweightパターンはその消去と抽出のアートを具現化するパターンである。