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が必要か?

❌ 抽象と実装が密結合だと、組み合わせに爆発的なクラス数が必要になる

例:

  • Shape(形) × Renderer(描画方法)
    VectorCircle, RasterCircle, VectorSquare, RasterSquare×2でクラス爆発

✅ Bridgeにより、抽象と実装を別レイヤーとして独立に構成

circle = Circle(renderer)
circle.draw()

Rendererを入れ替えるだけで、同じ抽象構造で異なる描画を実現可能


2. 基本構造

✅ Implementor(実装のインターフェース)

class Renderer:
    def render_circle(self, radius):
        raise NotImplementedError

✅ ConcreteImplementor(具体的な実装)

class VectorRenderer(Renderer):
    def render_circle(self, radius):
        print(f"ベクターで円を描画(半径: {radius}")

class RasterRenderer(Renderer):
    def render_circle(self, radius):
        print(f"ラスタで円を描画(ピクセルベース、半径: {radius}")

✅ 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):
        super().__init__(renderer)
        self.radius = radius

    def draw(self):
        self.renderer.render_circle(self.radius)

✅ 使用例

vector = VectorRenderer()
raster = RasterRenderer()

circle1 = Circle(vector, 5)
circle2 = Circle(raster, 10)

circle1.draw()
circle2.draw()

出力:

ベクターで円を描画(半径: 5)  
ラスタで円を描画(ピクセルベース、半径: 10)

3. Python的応用:依存性注入を通じてBridge構造を自然に実装

class Logger:
    def log(self, msg): raise NotImplementedError

class FileLogger(Logger):
    def log(self, msg): print(f"[FILE] {msg}")

class ConsoleLogger(Logger):
    def log(self, msg): print(f"[CONSOLE] {msg}")

class App:
    def __init__(self, logger: Logger):
        self.logger = logger

    def process(self):
        self.logger.log("アプリケーション処理開始")

AppはLoggerに依存しており、Bridgeによって実装に縛られない


4. 実務ユースケース

✅ GUIライブラリのプラットフォーム依存抽象化

抽象Widget + OSごとのRenderer


✅ ストレージ層(S3 / ローカル / DB)とアップロードAPIの分離

UploadService ⇄ StorageBackend


✅ ドキュメント出力(PDF / HTML / Markdown)の出力方式分離

Report ⇄ Renderer構造で表現


✅ 機械学習モデルの推論エンジン切り替え(TensorFlow / PyTorch)

ModelInterface ⇄ BackendExecutor


5. よくある誤用と対策

❌ 実装が少ないのにBridge構造にしてしまい複雑化

→ ✅ 抽象・実装が独立進化する可能性があるときだけ導入


❌ 実装部分の責務が過剰になりすぎる

→ ✅ Rendererや実装側に必要最小限の処理のみを委任


❌ 二重の継承関係で理解が難しくなる

→ ✅ 命名と責務の明確化で可読性を維持する


結語

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?