Bridge パターンとは
「橋渡し」のクラスを用意することによって、クラスを複数の方向に拡張させることを目的とする。
この「橋渡し」をする場所は、「機能のクラス階層」と「実装のクラス階層」である。
機能のクラス階層
新しい「機能」を追加したい場合、以下のような階層となる。
SomethingClass └ ChildSomethingClass └ GrandChildSomethingClass
実装のクラス階層
新しい「実装」を追加したい場合、以下のような階層となる。
SomethingAbstractClass └ ConcreteClass └ ConcreteClass2
example
以下のサンプルコードは「何かを表示」するためのもの。
DisplyaImpl 抽象クラス
<?php abstract class DisplayImpl { abstract public function rawOpen(); abstract public function rawPrint(); abstract public function rawClose(); }
Display クラス
<?php class Display { private $impl; public function __construct(DisplayImpl $impl) { $this->impl = $impl; } public function open() { $this->impl->rawOpen(); } public function print() { $this->impl->rawPrint(); } public function close() { $this->impl->rawClose(); } final public function display() { $this->open(); $this->print(); $this->close(); } }
CountDisplayクラス
<?php class CountDisplay extends Display { public function __construct(DisplayImpl $impl) { parent::__construct($impl); } public function multiDisplay(int $times) { $this->open(); for ($i = 0; $i < $times; $i++) { $this->print(); } $this->close(); } }
StringDisplayImplクラス
<?php class StringDisplayImpl extends DisplayImpl { private $string; private $width; public function stringDisplayImpl(string $string) { $this->string = $string; $this->width = strlen($string); } public function rawOpen() { $this->printLine(); } public function rawPrint() { echo "|" . $this->string . "|" . PHP_EOL; } public function rawClose() { $this->printLine(); } private function printLine() { echo "+"; for ($i = 0; $i < $this->width; $i++) { echo "-"; } echo "+" . PHP_EOL; } }
Main
<?php $d1 = new Display(new StringDisplayImpl("Hello, Japan.")); $d2 = new CountDisplay(new StringDisplayImpl("Hello, World.")); $d3 = new CountDisplay(new StringDisplayImpl("Hello, Universe.")); $d1->display(); $d2->display(); $d3->display(); $d3->multiDisplay(5);
実行結果
$ php Main.php +-------------+ |Hello, Japan.| +-------------+ +-------------+ |Hello, World.| +-------------+ +----------------+ |Hello, Universe.| +----------------+ +----------------+ |Hello, Universe.| |Hello, Universe.| |Hello, Universe.| |Hello, Universe.| |Hello, Universe.| +----------------+
ソースコード
役割
- Abstraction: 機能クラス階層の最上位クラス。Displayクラス
- FefinedAbstraction: 改善した抽象化の役。CountDisplayクラス
- Implementor: 実装者。実装のクラス階層の最上位クラス。DisplayImplクラス。
- ConcreteImplementor: 具体的な実装者。StringDisplayImplクラス。
まとめ
Bridgeパターンの特徴は「機能のクラス階層」と「実装のクラス階層」を分けている点。この2つのクラス階層を分けておけば、それぞれのクラス階層を独立に拡張できる。機能を追加したければ機能のクラス階層にクラスを追加する。このとき、実装のクラス階層は修正する必要がない。さらに、追加した機能は「すべての実装」で利用できる。
例として、OS依存の部分があるプログラムにBridgeパターンを適用することを考える。そのOS依存の部分をBridgeパターンの「実装のクラス階層」で表現し、各OS共通部分のインターフェースを決めてImplementor役とし、ConcreteImplementor役として各OS(win, mac, linuxなど)それぞれのクラスを作る。こうすることによって、「機能のクラス階層」側でいくら機能を追加しても、各OS同時に対応していることになる。
2種類のクラス階層に分離することで、クラス拡張を見通しよく行うことができる。
関連パターン
- PHP7でデザインパターン入門3/23 Template Methodパターン - Do Something
- PHP7でデザインパターン入門8/23 Abstract Factoryパターン - Do Something
- PHP7でデザインパターン入門2/23 Adapterパターン - Do Something
- 作者: 結城浩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2004/06/19
- メディア: 大型本
- 購入: 51人 クリック: 762回
- この商品を含むブログ (399件) を見る