2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonで構築するFlyweightパターン:メモリ効率を極限まで高める構造設計

Posted at

概要

Flyweight(フライウェイト)パターンは、
多数のオブジェクトが類似または同一の状態を持つ場合に、
共有可能な部分(不変な内部状態)を外部に分離・再利用することで、メモリ効率を最適化する構造的パターンである。

数百万単位で生成されるオブジェクト群の状態の重複を排除し、構造的に共有することで軽量化を実現する


1. なぜFlyweightが必要か?

❌ 同一状態のオブジェクトを大量に生成

for _ in range(1000000):
    glyphs.append(Character("A", "Arial", 12))

→ メモリを浪費し、スケーラビリティが著しく低下


✅ 共有可能な状態を外部化し、Flyweightで再利用

factory.get_char("A", "Arial", 12)

同一状態のインスタンスは1つだけ保持され、以後は共有参照


2. 基本構造

✅ Flyweightクラス(共有される軽量オブジェクト)

class Character:
    def __init__(self, char, font, size):
        self.char = char          # 内部状態(共有)
        self.font = font
        self.size = size

    def render(self, position):
        print(f"{self.char} [{self.font}, {self.size}] at {position}")

✅ FlyweightFactory(インスタンスのキャッシュ管理)

class CharacterFactory:
    def __init__(self):
        self._pool = {}

    def get(self, char, font, size):
        key = (char, font, size)
        if key not in self._pool:
            self._pool[key] = Character(char, font, size)
        return self._pool[key]

✅ 使用例

factory = CharacterFactory()

doc = []
for i in range(100):
    doc.append(factory.get("A", "Arial", 12))

# 実際に生成されたCharacterインスタンスは1つのみ
print(len(set(id(c) for c in doc)))  # → 1

3. Python的応用:@lru_cache によるFlyweight化

from functools import lru_cache

@lru_cache(maxsize=128)
def get_color(r, g, b):
    return (r, g, b)

color1 = get_color(255, 255, 255)
color2 = get_color(255, 255, 255)
assert color1 is color2  # 共有されている

不変オブジェクトのキャッシュにより、実質Flyweight化


4. 実務ユースケース

✅ ゲームにおけるキャラクター表示・粒子・地形要素

→ 同一グラフィック・属性を持つエンティティを効率よくレンダリング


✅ フォントレンダリング・文字表示システム

→ 文字ごとにオブジェクトを作らず、キャッシュで共有レンダリング


✅ 色・スタイル・アイコンの共通化

→ UI上の装飾情報を構造的に管理・再利用


✅ ファイルパーミッション・属性・ステータスの定義共有

→ 状態をクラス化し、同一内容を共通オブジェクトで表現


5. よくある誤用と対策

❌ 外部状態と内部状態の区別が曖昧

→ ✅ 共有可能な状態(フォント・サイズなど)は内部に、
位置や一時的な情報は外部で持つ


❌ 共有すべきでないオブジェクトまでキャッシュする

→ ✅ 状態が変化するものはFlyweightに適さない


❌ キャッシュが肥大化し、逆にメモリ消費が増大

→ ✅ maxsize を明示的に設定し、キャッシュ管理を明確に


結語

Flyweightパターンとは、“重複するデータを構造的に共有し、無駄をそぎ落とす設計技法”である。

  • 高頻度・大量オブジェクト生成時に、最小限のリソースで最大の表現を可能に
  • 内部状態と外部状態を分離し、オブジェクトの意味的重複を排除
  • Pythonでは dict@lru_cache、オブジェクトIDの比較で、直感的な実装が可能

Pythonicとは、“同じものは使い回す”という合理性に基づいた設計であり、
Flyweightパターンはその節制と効率性を、メモリに染み込ませるための技術である。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?