0
0

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で実装するCompositeパターン:構造を木構造に抽象化して統一的に扱う

Posted at

概要

Composite(コンポジット)パターンは、
個と集合を同一のインターフェースで扱えるようにする設計パターンである。

ツリー構造(階層構造)を表現し、葉(Leaf)と枝(Composite)を一貫した操作で処理可能にする。
GUI、ファイルシステム、HTML構文木、数式木など、再帰的な構造を扱う領域において極めて有効


1. なぜCompositeが必要か?

❌ ノードとコンテナで異なるロジックが必要になり、分岐処理が煩雑になる

if isinstance(node, Folder):
    for child in node.children:
        ...
else:
    process(node)

個別に処理を書く必要があり、拡張性が著しく低下


✅ 個(Leaf)と集合(Composite)を共通インターフェースで扱えるようにする

root.render()

再帰構造を意識せず、構成要素を一貫して操作可能


2. 基本構造

✅ Component(共通インターフェース)

class Graphic:
    def render(self):
        raise NotImplementedError

✅ Leaf(個体)

class Circle(Graphic):
    def render(self):
        print("● Circleを描画")

✅ Composite(集合)

class Group(Graphic):
    def __init__(self):
        self._children = []

    def add(self, graphic: Graphic):
        self._children.append(graphic)

    def render(self):
        print("Group開始")
        for child in self._children:
            child.render()
        print("Group終了")

✅ 使用例

circle1 = Circle()
circle2 = Circle()
group = Group()
group.add(circle1)
group.add(circle2)

root = Group()
root.add(group)
root.add(Circle())

root.render()

出力:

Group開始  
Group開始  
● Circleを描画  
● Circleを描画  
Group終了  
● Circleを描画  
Group終了

3. Python的応用:__iter__yield from によるツリーのトラバース

class Group(Graphic):
    def __iter__(self):
        for child in self._children:
            if isinstance(child, Group):
                yield from child
            else:
                yield child

再帰構造をfor文で簡潔に処理可能にする


4. 実務ユースケース

✅ UIコンポーネントツリー(ボタン、ラベル、パネル)

→ 各コンポーネントを統一されたrender()で描画処理


✅ ファイルシステム(ファイルとフォルダ)

ファイルもフォルダも共通インターフェースで操作可能


✅ 数式木・構文解析(AST)

項と演算子のノードを一貫して評価・解析


✅ メニュー構造(ネストされたメニュー・サブメニュー)

→ 表示・切替など動作を共通化


5. よくある誤用と対策

❌ コンポジットオブジェクトがリーフに依存しすぎて設計が崩れる

→ ✅ 共通インターフェースを厳密に守り、各役割に責務を限定する


❌ コンポジットがリーフ以外も自由に受け入れてしまう

→ ✅ 子要素は Graphic インターフェースを実装しているか確認する


❌ リーフに不要な操作(add/remove)を持たせてしまう

→ ✅ リーフ側では未実装で NotImplementedError を返すのが自然


結語

Compositeパターンとは、“個と集合を統一的に扱い、再帰構造を抽象化する設計”である。

  • ツリー構造をシンプルにモデル化し、操作を一貫性あるAPIに統合
  • 再帰的な要素に対して、拡張性・保守性・可読性の高い構造が構築可能
  • Pythonではダックタイピングと再帰生成で、コンパクトで直感的に表現可能

Pythonicとは、“違いを意識せず一貫した操作を実現すること”。
Compositeパターンはその統一の知性を、階層構造に注ぎ込む技法である。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?