Pattern: 轉接頭模式
Class Diagram: 才藝表演
情境:以下是某才藝表演
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <?php
namespace App\AdapterPattern\TalentShow;
class Program {
public function run() { $result = [];
$pianoPlayer = new PianoPlayer(); $result[] = $pianoPlayer->play();
$jokeTeller = new JokeTeller(); $result[] = $jokeTeller->tell();
return $result; } }
|
主持人覺得需要知道,每位表演者的表演方式,有些麻煩。
希望我們定義一個統一的介面,讓他的主持工作能更順利。
需求一:定義表演介面,使得表演項目能夠被管理
隨著項目變多,每個人的表演都不一樣。
可能會有彈鋼琴、拉扯鈴、講笑話、演話劇等。
但是這些項目,未必都是為了才藝表演而存在。
讓我們以此為基礎,切分兩者的職責。
1 2 3 4 5 6 7 8
| <?php
namespace App\AdapterPattern\TalentShow\Contracts;
interface ShowInterface { public function show(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php
namespace App\AdapterPattern\TalentShow\Adapter;
use App\AdapterPattern\TalentShow\PianoPlayer; use App\AdapterPattern\TalentShow\Contracts\ShowInterface;
class PianoPlayerAdapter implements ShowInterface {
protected $pianoPlayer;
public function __construct(PianoPlayer $pianoPlayer) { $this->pianoPlayer = $pianoPlayer; }
public function show() { return $this->pianoPlayer->play(); } }
|
透過這個轉接頭,
當我們請鋼琴表演者表演時,
他就會開始彈鋼琴。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php
namespace App\AdapterPattern\TalentShow\Adapter;
use App\AdapterPattern\TalentShow\Contracts\ShowInterface; use App\AdapterPattern\TalentShow\JokeTeller;
class JokeTellerAdapter implements ShowInterface {
protected $jokeTeller;
public function __construct(JokeTeller $jokeTeller) { $this->jokeTeller = $jokeTeller; }
public function show() { return $this->jokeTeller->tell(); } }
|
透過這個轉接頭,
當我們請笑話表演者表演時,
他就會開始講笑話。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <?php
namespace App\AdapterPattern\TalentShow;
use App\AdapterPattern\TalentShow\Adapter\PianoPlayerAdapter; use App\AdapterPattern\TalentShow\Adapter\JokeTellerAdapter; use App\AdapterPattern\TalentShow\Contracts\ShowInterface;
class Program {
protected $performers = [];
public function run() { $this->preparePerformers();
$result = []; foreach ($this->performers as $performer) { $result[] = $performer->show(); }
return $result; }
private function preparePerformers() { $pianoPlayer = new PianoPlayer(); $this->performers[] = new PianoPlayerAdapter($pianoPlayer);
$jokeTeller = new JokeTeller(); $this->performers[] = new JokeTellerAdapter($jokeTeller); } }
|
透過各種實作表演介面的轉接頭,我們便能更好地管理表演項目了。
(比如:進退場的流程、項目的介紹等)
[單一職責原則]
我們將才藝類別與表演項目類別視作兩種不同的職責。
[開放封閉原則]
若我們需要在表演時,增加新的表演者,可以不修改原本才藝類別的程式碼。
只需新增一個對應的轉接頭。
[介面隔離原則]
才藝類別與表演項目類別實作的是兩個不同的接口。
透過轉接頭,讓原本接口不同的類別能夠介接。
[依賴反轉原則]
客戶端的程式碼依賴抽象的表演介面。
轉接頭實作抽象的表演介面。
ʕ •ᴥ•ʔ:除了上述包裹類別的方式外,轉接頭還能透過多重繼承的方式實現。
將來撰寫其他語言範例時,再來補充。