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(コンポジット)パターンは、
ツリー構造のデータや要素(ノード)を、個と集合の区別なく統一的に扱うための構造的デザインパターンである。

「フォルダとファイル」「組織階層」「UIのネスト構造」「抽象構文木」など、
入れ子構造をもつモデルを一貫性のあるインターフェースで操作する際に極めて有効である。


1. なぜCompositeが必要か?

❌ ファイルとフォルダを別々に扱う煩雑なコード

if isinstance(node, File):
    node.open()
elif isinstance(node, Folder):
    for child in node.children:
        child.open()

→ 個(File)と集合(Folder)でインターフェースが異なり、分岐が増えて保守が困難


✅ 共通のインターフェースで統一的に扱う

node.open()

構造に依存せず一貫して処理できる


2. 基本構造

✅ コンポーネント基底クラス

class Component:
    def operation(self):
        raise NotImplementedError

✅ リーフノード(個)

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

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

✅ コンポジットノード(集合)

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

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

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

✅ 使用例

root = Folder("root")
root.add(File("file1.txt"))
root.add(File("file2.txt"))

subfolder = Folder("sub")
subfolder.add(File("nested.txt"))

root.add(subfolder)
root.operation()
Entering folder: root
Opening file: file1.txt
Opening file: file2.txt
Entering folder: sub
Opening file: nested.txt

3. Python的応用:ダックタイピングでの柔軟設計

Pythonでは抽象基底クラスにこだわらずとも、
operation() を持つオブジェクトをコンポジットの要素とみなすことで柔軟な構造が可能。

class PrintCommand:
    def __init__(self, message):
        self.message = message

    def operation(self):
        print(self.message)
flow = Folder("print sequence")
flow.add(PrintCommand("Start"))
flow.add(PrintCommand("Loading..."))
flow.add(PrintCommand("Done"))
flow.operation()

4. 実務ユースケース

✅ ファイルシステム構築・ナビゲーション

→ ディレクトリとファイルを同一操作で扱える


✅ 組織図の表現(部署と個人)

→ 各階層が同一インターフェースで指令を受ける構造に適応


✅ UIコンポーネントのネストレンダリング

→ 画面要素の描画を render() の再帰呼び出しで実現可能


✅ 数式や構文ツリーの評価

→ リーフ(数字)とコンポジット(加算、減算など)を統一して解釈


5. よくある誤用と対策

❌ リーフとコンポジットで無理に同じ処理を持たせる

→ ✅ operation() の定義は共通だが、処理の実態はノード種別に適応


❌ リーフにも add() を実装してしまう

→ ✅ コンポジットのみに add() を持たせ、APIの明快さを維持


❌ コンポジット内部でリーフの型チェックを行う

→ ✅ 型に依存せず、共通インターフェースにのみ従う設計を心がける


結語

Compositeパターンとは、“構造の深さにかかわらず、操作を統一化する”ための抽象設計手法である。

  • 個と集合の間にある境界を抽象によって解消し、処理ロジックの一貫性とスケーラビリティを確保
  • 木構造やネスト構造において、柔軟かつ再帰的な操作を可能にする
  • Pythonのオブジェクト指向特性とマッチし、柔らかくも強い設計が可能

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?