概要
Bridge(ブリッジ)パターンは、
抽象(Abstraction)と実装(Implementation)を分離し、両者を独立に拡張可能にする設計パターンである。
機能の階層(例:図形やレポート)と、その実装手段(例:描画方式や出力形式)を分けることで、
組み合わせ爆発を防ぎ、構造を柔軟かつ明快に設計できる。
1. なぜBridgeが必要か?
❌ 機能と実装を階層的に継承すると、クラス数が爆発する
- Circle → SVGCircle / PNGCircle
- Square → SVGSquare / PNGSquare
→ 2 × 2 → 4クラス、3 × 3 → 9クラス… 組み合わせ地獄に突入
✅ 抽象と実装を別ツリーで設計し、コンポジションで柔軟に結合
circle = Circle(SVGRenderer())
circle.draw()
→ 実装を差し替えることで、機能はそのままに動作だけ変更できる
2. 基本構造
✅ Implementation(実装インターフェース)
class Renderer:
def render_circle(self, radius):
raise NotImplementedError
✅ ConcreteImplementations(具体的な実装)
class SVGRenderer(Renderer):
def render_circle(self, radius):
print(f"<circle r='{radius}' />")
class ASCIIArtRenderer(Renderer):
def render_circle(self, radius):
print(f"● 半径{radius}の円(ASCII表示)")
✅ Abstraction(抽象インターフェース)
class Shape:
def __init__(self, renderer: Renderer):
self.renderer = renderer
def draw(self):
raise NotImplementedError
✅ RefinedAbstraction(具体的な抽象)
class Circle(Shape):
def __init__(self, renderer: Renderer, radius: int):
super().__init__(renderer)
self.radius = radius
def draw(self):
self.renderer.render_circle(self.radius)
✅ 使用例
circle_svg = Circle(SVGRenderer(), 10)
circle_ascii = Circle(ASCIIArtRenderer(), 5)
circle_svg.draw() # <circle r='10' />
circle_ascii.draw() # ● 半径5の円(ASCII表示)
出力:
<circle r='10' />
● 半径5の円(ASCII表示)
3. Python的応用:関数を渡すことで動的Bridgeを構築
class Circle:
def __init__(self, draw_func, radius):
self.draw_func = draw_func
self.radius = radius
def draw(self):
self.draw_func(self.radius)
circle = Circle(lambda r: print(f"○ 半径{r} の円です"), 7)
circle.draw()
→ 関数やクラスを“ブリッジ”として渡すことで、動的な結合が可能
4. 実務ユースケース
✅ UIとテーマ(ライト/ダーク/高コントラスト)
→ UI構造とスタイルレンダリングを分離
✅ チャートと出力形式(HTML/PDF/PNG)
→ チャートの種類 × 出力方式を柔軟に拡張
✅ ロギングと出力先(コンソール/ファイル/リモート)
→ ロガー構造と転送手段を切り離す
✅ サービスと通信手段(REST/gRPC/WebSocket)
→ 同じAPI抽象に対して複数のプロトコルを実装
5. よくある誤用と対策
❌ 実装と抽象の分離が中途半端で、片方に依存が寄る
→ ✅ 「両者が独立に拡張できるか」を設計基準とする
❌ 実装の差し替えが前提でないのにBridgeを採用
→ ✅ 戦略的に差し替え・共通化が必要な場面に限定する
❌ Bridgeが巨大化し、責務が膨張する
→ ✅ Abstractionはロジックに徹し、Implementationは手段に徹する
結語
Bridgeパターンとは、“機能と手段を分けて考えることで、構造を自在に交差させる設計”である。
- 機能側(抽象)と実装側を独立に管理することで、柔軟で拡張性の高い構造が実現可能
- 組み合わせ爆発を抑えつつ、設計上の可読性・責務分離を強化
- Pythonではクラス・関数の双方を用いて、構造的な分離と合成を簡潔に実装可能
Pythonicとは、“足し算ではなく掛け算で構造を広げること”。
Bridgeパターンはその柔軟性の知性を、設計の交差点として昇華する技法である。