概要
Visitor(ビジター)パターンは、
データ構造(オブジェクト群)の定義を変更することなく、
新しい振る舞い(操作)を追加可能にするための構造的デザインパターンである。
この設計により、「構造」と「振る舞い」を分離し、
オブジェクトに新たな処理を注入することが可能となる。
1. なぜVisitorが必要か?
❌ オブジェクトクラスに振る舞いが集中する設計
class File:
def print(self):
...
def export(self):
...
→ ファイルの構造に新しい処理を加えるたびに、クラスの肥大化と責務の分散が発生
✅ 振る舞いはVisitorクラスに切り出して注入する
class PrintVisitor:
def visit_file(self, file): ...
→ 構造定義を触らずに振る舞いの追加・変更が可能
2. 基本構造
✅ Element(訪問される側)
class Element:
def accept(self, visitor):
raise NotImplementedError
class File(Element):
def __init__(self, name):
self.name = name
def accept(self, visitor):
visitor.visit_file(self)
✅ Visitor(振る舞いを定義する側)
class Visitor:
def visit_file(self, file):
raise NotImplementedError
class PrintVisitor(Visitor):
def visit_file(self, file):
print(f"[Print] File name: {file.name}")
✅ 使用例
file = File("document.txt")
visitor = PrintVisitor()
file.accept(visitor) # → [Print] File name: document.txt
3. Python的応用:ダブルディスパッチの活用
class Folder(Element):
def __init__(self, children):
self.children = children
def accept(self, visitor):
visitor.visit_folder(self)
class CountVisitor(Visitor):
def __init__(self):
self.count = 0
def visit_file(self, file):
self.count += 1
def visit_folder(self, folder):
for item in folder.children:
item.accept(self)
f1 = File("a.txt")
f2 = File("b.txt")
folder = Folder([f1, f2])
visitor = CountVisitor()
folder.accept(visitor)
print(visitor.count) # → 2
→ 構造を歩きながら異なる型に応じた処理を実行
4. 実務ユースケース
✅ 抽象構文木(AST)のトラバースと評価
→ 構文要素ごとに処理(例:プリント/変換/最適化)を注入
✅ ファイルシステムやXMLの構造解析
→ ファイル/フォルダ/属性などのツリー構造に対して統一されたアクセス
✅ データモデルへの複数操作(表示、エクスポート、検証)
→ データ構造を変更せず表示・保存・検査の各処理を独立して管理
✅ ゲームエンジン内のエンティティ評価処理
→ 位置計算、AI判定、エフェクト適用など一括処理を分離して追加可能
5. よくある誤用と対策
❌ VisitorがすべてのElementに依存
→ ✅ Visitorを分割して関心の分離を保つ(Single Responsibility Principle)
❌ accept() メソッドの未実装
→ ✅ 各Element型に明示的に accept(visitor)
を実装し、動的な振る舞い注入を保証
❌ Visitorにロジックが集中しすぎる
→ ✅ Visitorは操作の集合体であって、構造の責任を持たない
結語
Visitorパターンとは、“構造に手を加えず、振る舞いだけを柔軟に追加する”ための構造的技法である。
- 型ごとの処理をVisitorに集約することで、拡張性と保守性を同時に満たす
- 実行対象が複数種類のオブジェクトを持つ場合に、構文的に洗練されたディスパッチ処理を実現
- Pythonにおいても動的ディスパッチの仕組みとクラス構造の活用により、自然かつ強力なVisitor設計が可能
Pythonicとは、“構造と振る舞いを分離し、明快な責務で再構成する”ことであり、
Visitorパターンはその設計的透明性と柔軟性をコードに浸透させる知的戦略である。