Bridge パターン

Bridge パターンとは



Bridge パターンは、GoF(Gang of Four)によって定義されたデザインパターンの一つです。このパターンは、クラスを複数の方向に拡張するために「橋渡し」となるクラスを導入することを目的としています。具体的には、クラスの複雑な継承構造を解消し、より柔軟で再利用性の高い設計を目指します。

Bridge パターンのクラス図



Bridge パターンの基本的なクラス図は以下のようになります。

mermaid
classDiagram
class Abstraction {
<>
implementor: Implementor
operation()
}
class RefinedAbstraction {
Abstraction <|-- RefinedAbstraction
operation()
}
class Implementor {
<>
operationImpl()
}
class ConcreteImplementorA {
Implementor <|-- ConcreteImplementorA
operationImpl()
}
class ConcreteImplementorB {
Implementor <|-- ConcreteImplementorB
operationImpl()
}
Abstraction -- Implementor : uses



`Abstraction`クラスは抽象的なインターフェースを定義し、`Implementor`は実装の詳細を定義します。`RefinedAbstraction`は`Abstraction`を拡張し、`ConcreteImplementorA`と`ConcreteImplementorB`は`Implementor`の具体的な実装を提供します。

Bridge パターンの適用例



Bridge パターンの適用が望ましいクラス構造の例として、以下のような食器のクラス階層を考えてみましょう。

mermaid
classDiagram
class Dishware {
<>
}
Dishware <|-- Plate
Dishware <|-- Bowl
Plate <|-- WoodenPlate
Plate <|-- GlassPlate
Bowl <|-- WoodenBowl
Bowl <|-- GlassBowl

class Plate {
}
class Bowl {
}
class WoodenPlate {
}
class GlassPlate {
}
class WoodenBowl {
}
class GlassBowl {
}


この例では、`Dishware`(食器)クラスから`Plate`(皿)と`Bowl`(ボウル)クラスが派生しています。さらに、`Plate`からは`WoodenPlate`(木製の皿)と`GlassPlate`(ガラス製の皿)が、`Bowl`からは`WoodenBowl`(木製のボウル)と`GlassBowl`(ガラス製のボウル)が派生しています。

しかし、このクラス階層には以下のような問題があります。

1. クラスの追加が困難: プラスチック製の食器を新たにサポートしようとする場合、`Plate`クラスと`Bowl`クラスの両方を継承する必要があります。また、`Dishware`クラスのサブクラスとして`Cup`クラスを追加する場合、`WoodenCup`や`GlassCup`も同時に作成しなければなりません。
2. コードの複製が発生: `WoodenPlate`と`WoodenBowl`、`GlassPlate`と`GlassBowl`はそれぞれ同じ材質の食器であるため、内部的に似たような性質を持つ可能性があります。しかし、継承関係の都合上、これらのクラスはすべて個別に定義する必要があり、結果として同じようなコードを重複して記述することになります。

これらの問題の原因は、クラス階層の中に複数の継承関係が混在していることです。`Dishware`と`Plate`および`Bowl`の関係は、食器の種類による継承関係と見なすことができます。一方で、`Plate`と`WoodenPlate`および`GlassPlate`の関係は、食器の材質による継承関係と見なすことができます。このように複数の継承関係が存在することにより、一つの継承関係が他の継承関係に悪影響を及ぼしています。

Bridge パターンによる改善



このクラス構造をBridgeパターンを適用することで、以下のように改善できます。

mermaid
classDiagram
class Dishware {
<>
material: Material
use()
}
class Plate {
Dishware <|-- Plate
use()
}
class Bowl {
Dishware <|-- Bowl
use()
}
class Material {
<>
getMaterial()
}
class Wooden {
Material <|-- Wooden
getMaterial()
}
class Glass{
Material <|-- Glass
getMaterial()
}
Dishware
-- Material : uses




このクラス図では、`Dishware`から派生する継承関係は食器の種類のみであり、材質に関する情報は`Material`(素材)クラスに委譲しています。これにより、種類と材質はそれぞれ独立して拡張することができ、クラスの数も減らすことができます。

この構造により、例えば新しい素材を追加したい場合、`Material`インターフェースを実装した新しいクラス(例えば`Plastic`クラス)を追加するだけで済みます。`Plate`や`Bowl`などのクラスを修正する必要はありません。また、`Cup`クラスを追加する場合も、`WoodenCup`や`GlassCup`を同時に作成する必要はなく、`Cup`クラスと`Material`の組み合わせで実現できます。

まとめ



Bridgeパターンは、クラスの複雑な継承構造を解消し、柔軟で拡張性の高いシステムを構築するための強力なツールです。継承による組み合わせ爆発を避けるために、独立して変更できる抽象化と実装を分離することが重要です。このパターンを理解し適用することで、よりメンテナンス性の高いコードを作成できます。

関連項目



デザインパターン)
継承)

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。