Bridge パターン - ブリッジパターン
2008/06/27 21:43Update
Bridge パターンはGoFによる23種類のデザインパターンの構造に関連するパターンです。Bridge パターンでは、「橋渡し」役のクラスの概念とその実装を分離することによって、拡張性と柔軟性に優れたクラスを実装することができます。
Bridgeパターン 概要
オブジェクト指向設計にSRP単一責任原則というクラス設計の原則があります。
Single Responsibility Principle (SRP) - OO設計のSRP単一責任原則
Bridgeパターンは、クラスのカプセル化、結合(委譲)、及び継承などによって、それぞれのクラスにそれぞれの責任(役割)を担当させ、「橋渡し」役のクラスの概念とその実装を分離することで、クラスの拡張をより容易になります。
簡単に言いますと、
Aクラスは「a機能」を提供するとします。
「a機能」の実装はAクラスではなく、Bというクラスに 「a機能」 を実装してもらいます。
もちろん、クライアントは、Aクラスをしか知りませんので、Aクラスは「橋渡し」という役割でBの「a機能」をクライアントに提供します。
即ち、
Aは抽象(Abstraction)概念(インタフェース)を定義します
Bはその機能を実装(Implementation)します。
Aは委譲という方式でBの機能を呼出し、クライアントに提供します。
では、なぜ、Aクラスにその機能を実装しないのでしょうか?
Bridgeパターン の使用シーン
クラスの責任の分離
◇ クラスに一つ以上の役割(責任)を担っている場合、そのクラスを複数のクラスに分割すべきである。
Single Responsibility Principle (SRP) - OO設計のSRP単一責任原則
オブジェクト指向においては、クラス(又はインタフェース)は、複数の派生クラスを存在する場合、これらの派生クラスは:
◇ 複数の並行状態(あるいは相互に排他的な複数の状態)である。
◇ 概念又は継承関係が混在(交差)している。
◇ 変化する可能性がある。
例から説明します。
自動車(Car)は、その派生クラスにはトラック(Truck)、とバス(Bus)があるとします。
また、トラック(Truck)や、バス(Bus)はそれぞれ1500cc(Car1500)や2000cc(Car2000)の種類があるとします。
当然、1500ccのトラックにしても、2000ccのトラック、1500ccのバス、2000ccのバスにしても、すべては自動車(Car)です。
このような場合、自動車(Car)クラス及びその派生クラスは:
◇ 複数の並行状態(あるいは相互に排他的な複数の状態)である。自動車の種類(Truck、Bus)とエンジン(1500cc、2000cc)は自動車のそれぞれの並行状態である。
◇ 概念又は継承関係が混在(交差)している。トラック(Truck)とバス(Bus)は、両方とも1500ccと2000ccのエンジンがある。
◇ 変化する可能性がある。自動車はトラック(Truck)、とバス(Bus)だけではなく、他の種類の自動車もある、エンジンも2500ccや3000ccなどがある。
このような場合、クラスの継承関係はどうすべきでしょうか?
方法一:継承による実装(X)
自動車抽象クラス:Car
自動車派生クラス - 種類よる分類:Bus,Truck
自動車派生クラス - エンジンよる分類:Bus1500,Bus2000,Truck1500,Truck2000
この方法だと、
◇ 拡張しにくい。仮に「他の自動車」もしくは「エンジン」を一つでも追加した場合、その派生クラスの数は倍増になってしまいます。
例えば、救急車(FireCar)を一つ、2500エンジンを一つ追加した場合、Bus1500,Bus2000,Bus2500,Truck1500,Truck2000,Truck2500,FireCar1500,FireCar2000,FireCar2500これだけ数のクラスを実装しなければなりません。
◇ コードの重複。Bus1500とTruck1500の自動車のエンジンは同じく1500ccであるため、エンジンの操作は同じですが、同時に複数のクラスに同じようなコードを書かなければなりません。
方法二:メソッドの追加による実装(X)
自動車抽象クラス:Car
自動車派生クラス - 種類よる分類:Bus,Truck
Busというクラスに1500cc及び2000ccの設置という機能を提供します
Bus extends Car {
public setEngine1500cc();
public setEngine2000cc();
}
同様、Truckというクラスにも1500cc及び2000ccの設置という機能を提供します。
Truck extends Car {
public setEngine1500cc();
public setEngine2000cc();
}
この場合、自動車の種類を追加(拡張)する場合、派生クラスの数をそんなに増やしませんが、エンジンを追加する場合、すべての派生クラスを修正しなければなりません。
また、コードの重複も避けられません。
Bridgeパターンを利用すれば、このような問題を解決できます。
Bridgeパターン のクラス図
<<クラス図>>
Client
Bridgeパターンのクライアント
Abstraction
橋渡し役。抽象クラス。
機能実装クラス(Implementor)のインスタンスを保持している。
Implementorより上のレベルの機能を定義
RefinedAbstraction
Abstraction具体的な実装。具体的な機能はImplementorに委譲。
Implementor
機能実装クラスの抽象インタフェース 。
ConcreteImplementor
Implementorの具体的な実装。
次のページ:Bridgeパターン の使用例
Sponsored Link
- Relative Articles
- ASP.NETでのフロント・コントローラ(Front Controller)実装 - (2009/10/20 15:22)
- Factory Method パターン - ファクトリメソッドパターン - (2008/06/09 22:44)
- Abstract Factory パターン - 抽象ファクトリパターン - (2008/06/10 13:25)
- Singleton パターン - シングルトンパターン - (2008/06/10 15:36)
- Prototypeパターン - プロトタイプパターン - (2008/06/10 17:23)
- Builderパターン - ビルダーパターン - (2008/06/10 19:01)
- Adapter パターン - アダプターパターン - (2008/06/11 11:30)
- Composite パターン - コンポジットパターン - (2008/06/11 16:59)
- Interpreter パターン - インタプリタパターン - (2008/06/13 15:42)
- Chain of Responsibility パターン - 責任の連鎖パターン - (2008/06/14 00:28)