Bridge
Tweet「何を行うのか(機能)」と「どのような処理をするのか(実装)」それぞれの拡張方法を分けるパターン。
「何を行うのか(機能)」を実装する場合は、「どのような処理をするのか(実装)」を意識しなくても良いのが利点。
Bridgeパターンは先日のAdapter パターンと非常によく似ているが、
Adapterパターンは既存のクラス
を再利用するために導入する後天的な理由に対し、
Bridgeパターンは設計の段階
で分離するという先天的な理由で導入されるのが大きな違い。
また、よくOOPを学び始めにやりがちな継承の失敗(is-a関係から外れた継承)を起こしにくいので積極的に導入したい。
例
XMLかHTML5からタイトルを取得する。
UML
重要なところ
どのような処理をするのか
を実装する。
何を行うのか
を実装する。
これで、
- 何を行うのか(WebScraper)
- どのような処理をするのか(PageParser,DOMParser,XPathParser)
が分離された状態になる。
PHPで書いてみる
PageParser1
2
3
4interface PageParser
{
public function getTitle() : string;
}
DOMParser1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class DOMParser implements PageParser
{
prviate $document;
public function __construct(DOMDocument $document)
{
$this->document = $document;
}
public function getTitle() : string
{
$element = $this->document->getElementsByTagName('title')->item(0);
return $element->textContent ?? '';
}
}
DOMParserがどのような処理をするのか
を表している。
この例ではDOMDocumentを取得して、titleタグの1つ目のテキストを取得している。
WebScraper1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class WebScraper
{
protected $pageParser;
public function __construct(PageParser $pageParser)
{
// このクラスはどのように処理するのかを委譲している
$this->pageParser = $pageParser;
}
public function getTitle() : string
{
return $this->pageSource->getTitle();
}
}
WebScraperが何をするのか
のコード。
WebScraperは、PageParserクラスをプロパティで保持して、
具体的にgetTitleでどのような処理をするのかをPageParserに委譲している。
このようにWebScraperが何をするのか
とどのように処理するのか
の橋渡し
をしている。
ここでタイトルの一部分だけを取得する機能が拡張された場合でも
1 | class HyperWebScraper extends WebScraper |
このように何をするのか
は具体的なタイトルを取得する処理を知ることなく実装することができる。
Client Code1
2
3
4
5
6
7
8
$doc = new DOMDocument();
$doc->loadHTMLFile('example.html');
$pageSource = new DOMParser($doc);
$webScraper = new WebScraper($pageSource);
echo $webScraper->getTitle();
まとめ
何を行うのか
とどのような処理をするのか
を分離する。何を行うのか
を実装する場合は、どのような処理をするのか
を意識しなくても良い。- 委譲で実装する。