用 PHP 連結的方法
方法連結是 Martin Fowler 的書“ Domain Specific Languages”中 解釋的一種技術。方法連結總結為
考慮這段非連結/常規程式碼(從前面提到的書中移植到 PHP)
$hardDrive = new HardDrive;
$hardDrive->setCapacity(150);
$hardDrive->external();
$hardDrive->setSpeed(7200);
方法連結允許你以更緊湊的方式編寫上述語句:
$hardDrive = (new HardDrive)
->setCapacity(150)
->external()
->setSpeed(7200);
你需要做的就是在你想要連結的方法中使用 return $this
:
class HardDrive {
protected $isExternal = false;
protected $capacity = 0;
protected $speed = 0;
public function external($isExternal = true) {
$this->isExternal = $isExternal;
return $this; // returns the current class instance to allow method chaining
}
public function setCapacity($capacity) {
$this->capacity = $capacity;
return $this; // returns the current class instance to allow method chaining
}
public function setSpeed($speed) {
$this->speed = $speed;
return $this; // returns the current class instance to allow method chaining
}
}
何時使用它
使用方法鏈的主要用例是構建內部域特定語言。方法鏈是一個構建塊中表達的建設者和流利的介面 。但它並不是那些同義詞 。方法連結只能啟用那些。引用福勒:
我也注意到了一個常見的誤解 - 許多人似乎將流暢的介面等同於 Method Chaining。當然連結是一種常用的技術,可以使用流暢的介面,但真正的流暢性遠不止於此。
話雖如此,使用 Method Chaining 只是為了避免編寫宿主物件被許多人認為是程式碼味道 。它會產生不明顯的 API,尤其是在與非連結 API 混合時。
補充說明
命令查詢分離
命令查詢分離是 Bertrand Meyer 提出的設計原則 。它宣告變異狀態( 命令 )的方法不應該返回任何東西,而返回某些東西( 查詢 )的方法不應該改變狀態。這使得更容易推理系統。方法連結違反了這個原則,因為我們正在改變狀態並返回一些東西。
getter
當使用實現方法連結的類時,在呼叫 getter 方法時要特別注意(即返回 $this
之外的其他方法)。由於 getter 必須返回以外的值比 $this
,連結的附加方法到 getter 使得呼叫的操作得到的值,而不是原始物件上。雖然鏈式 getter 有一些用例,但它們可能會降低程式碼的可讀性。
得墨忒耳定律及對測試的影響
方法如上所述連結不違反得墨忒耳定律 。它也不會影響測試。那是因為我們正在返回主機例項,而不是一些協作者。這是一種常見的錯誤觀念,源於人們將方法連結與 Fluent Interfaces 和 Expression Builders 混淆。只有當 Method Chaining 返回其他物件而不是主機物件時,才會違反 Demeter 法並在測試中結束模擬測試。