2
3

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)を同一のインターフェースで扱うことで、
ツリー構造のような階層的なオブジェクトを透過的に処理可能にする再帰的構造設計パターンである。

これにより、個別要素と複合要素を統一的に操作できるため、
再帰的な構造を持つドメイン(ファイルシステム、UIコンポーネント、シーン構造など)に適用される。


1. なぜCompositeパターンが必要か?

❌ 個と集合を分けて処理する複雑なロジック

for item in items:
    if isinstance(item, Leaf):
        item.operation()
    else:
        for sub in item.children:
            sub.operation()

処理の分岐が必要となり、コードが汚染される


✅ 個も集合も同一の操作インターフェースを持つ

root.operation()

ノードとツリー全体を同様に扱える再帰的かつ透過的な設計に


2. 基本構造

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

class Component:
    def operation(self):
        raise NotImplementedError

✅ Leaf(個のオブジェクト)

class Leaf(Component):
    def __init__(self, name):
        self.name = name

    def operation(self):
        print(f"Leaf: {self.name}")

✅ Composite(子を持つオブジェクト)

class Composite(Component):
    def __init__(self, name):
        self.name = name
        self.children = []

    def add(self, component: Component):
        self.children.append(component)

    def operation(self):
        print(f"Composite: {self.name}")
        for child in self.children:
            child.operation()

✅ 使用例

root = Composite("root")
child1 = Leaf("A")
child2 = Leaf("B")
child_group = Composite("group1")
child_group.add(Leaf("C"))
child_group.add(Leaf("D"))

root.add(child1)
root.add(child2)
root.add(child_group)

root.operation()

出力:

Composite: root
Leaf: A
Leaf: B
Composite: group1
Leaf: C
Leaf: D

3. Python的応用:__iter__で再帰的走査を可能に

class CompositeIterable(Composite):
    def __iter__(self):
        for child in self.children:
            yield child
            if isinstance(child, CompositeIterable):
                yield from child
tree = CompositeIterable("root")
tree.add(Leaf("1"))
sub = CompositeIterable("sub")
sub.add(Leaf("2"))
tree.add(sub)

for node in tree:
    node.operation()

ツリー構造をPythonイテレータで柔らかく展開可能に


4. 実務ユースケース

✅ ファイルシステムの構造表現

→ フォルダ(Composite)とファイル(Leaf)を統一的に操作


✅ UIコンポーネントツリーの構築

→ ボタン、ラベル、パネルなどを再帰的に組み合わせて描画


✅ シーン構造やゲームオブジェクトの管理

→ 子ノードを持つEntity構造のトラバース処理に活用


✅ ドキュメント・HTMLなどの構文構造表現

→ セクション、段落、テキストを階層的にレンダリング処理


5. よくある誤用と対策

❌ 子要素の追加・削除をLeafにも許容してしまう

→ ✅ Leafは add/remove を持たず、Composite専用に定義する


❌ コンポーネント間の依存性が密結合

→ ✅ Componentインターフェースを厳格に定義し、個と集合の責務を明確に分離


❌ 複雑すぎる再帰構造をそのまま出力してしまう

→ ✅ 再帰処理における深さや出力制御を適切に設計する


結語

Compositeパターンとは、“個と集合を統一的に扱い、階層構造を透過的に表現するための構造デザイン”である。

  • 再帰的構造において、共通インターフェースによる柔軟で一貫した操作が可能に
  • ツリー構造の設計において、構造と処理の責務分離を明確化
  • Pythonではクラスと動的な型の組み合わせにより、型安全かつ柔軟にComposite構造を構築可能

Pythonicとは、“複雑な構造も一つの統一的な視点で捉える”ことであり、
Compositeパターンはその抽象と具体を、コードの中で優雅に溶け合わせる設計手法である。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?