用 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 法并在测试中结束模拟测试。