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で実装するBridgeパターン:抽象と実装の分離による柔軟な構造設計

Posted at

概要

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パターンはその柔軟性の知性を、設計の交差点として昇華する技法である。

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?