2
4

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(フライウェイト)パターンは、
大量に生成されるオブジェクトの中で状態が共通している部分を共有し、必要最小限のメモリ消費で動作させる構造パターンである。

特にゲーム・UI・文字処理・描画システムなど、同種のオブジェクトが大量に発生する領域で効果を発揮する。


1. なぜFlyweightが必要か?

❌ 毎回新しいオブジェクトを作る設計

for _ in range(10000):
    icon = Icon("folder.png")

→ 同じ画像・構造にもかかわらず、メモリに1万個の実体が生成される


✅ 共通部分を共有し、最小限のインスタンス化に留める

icon1 = factory.get_icon("folder.png")
icon2 = factory.get_icon("folder.png")
assert icon1 is icon2  # 同一インスタンス

共通の内部状態は1つに保ち、外部状態のみを個別に持つ構造へ


2. 基本構造

✅ Flyweight(共有されるオブジェクト)

class Icon:
    def __init__(self, filename):
        self.filename = filename

    def draw(self, position):
        print(f"{self.filename}{position} に描画")

✅ FlyweightFactory(インスタンス共有管理)

class IconFactory:
    def __init__(self):
        self._icons = {}

    def get_icon(self, filename):
        if filename not in self._icons:
            self._icons[filename] = Icon(filename)
        return self._icons[filename]

✅ 使用例

factory = IconFactory()
icon1 = factory.get_icon("folder.png")
icon2 = factory.get_icon("folder.png")

icon1.draw("top-left")
icon2.draw("bottom-right")

print(icon1 is icon2)  # → True

3. Python的応用:文字列や色の共有

class Color:
    def __init__(self, name):
        self.name = name

class ColorFactory:
    _cache = {}

    @classmethod
    def get(cls, name):
        if name not in cls._cache:
            cls._cache[name] = Color(name)
        return cls._cache[name]
c1 = ColorFactory.get("red")
c2 = ColorFactory.get("red")
print(c1 is c2)  # True

イミュータブルなデータを中心に、明示的なキャッシュを使った軽量化


4. 実務ユースケース

✅ フォント・アイコン・スプライトの共有描画

→ UI上の同一画像リソースを再利用して描画コストを削減


✅ 文字列解析や構文木の再利用(例:トークンの共有)

→ トークンやキーワードの同一インスタンス化により高速処理


✅ 地図上のピンやマーカーの共通構造管理

→ 共通の見た目を共有し、位置やラベルのみ外部状態として持たせる


✅ HTML DOMの仮想化(例:Reactの仮想DOM)

→ 構造の再利用と状態差分による描画最適化


5. よくある誤用と対策

❌ 外部状態を共有してしまう

→ ✅ 共有されるのは「内部状態」のみ、外部状態は使用側で個別に保持すべき


❌ キャッシュが肥大化しすぎる

→ ✅ Factoryにキャッシュ破棄・再利用の適切な制御機構を導入する


❌ 可変オブジェクトをFlyweightとして共有する

→ ✅ イミュータブルであることが前提。可変な場合はコピーやクローンを用意すべき


結語

Flyweightパターンとは、“共通の重さ(weight)を一つにまとめて、多数の個体を軽く保つ”ための設計技法である。

  • オブジェクトの内部状態を共有することで、メモリ使用量を最小限に抑えながら高パフォーマンスを実現
  • 状態の分離(内部と外部)によって、柔軟な表現と最適な資源管理を両立
  • Pythonではファクトリパターンや辞書ベースのキャッシュを活用することで、シンプルかつ強力なFlyweight構造を実装可能

Pythonicとは、“同じものは一つに、違うものは分けて”扱うこと。
Flyweightパターンはその効率的なリファクタリングの知恵を、構造に昇華させる技法である。

2
4
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
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?