我正在研究PSR-7接口并思考如何实现它们的方法.
我也一直在阅读这篇博文.显然,实现PSR-7接口的对象必须是不可变的.
因此,如果我从那时实现该withProtocolVersion方法,MessageInterface它将看起来像这样:
public function withProtocolVersion($version)
{
if ( $this->protocol === $version )
{
return $this;
}
$new = clone $this;
$new->protocol = $version;
return $new;
}
Run Code Online (Sandbox Code Playgroud)
我的问题确实是,为什么一成不变?为什么不简单地做一个return $this;?
并不是我担心它分配的内存量,我真的没有看到保持它不可变的任何好处.
就像博客文章所说,当你这样做时:
$request = $request
->withMethod('POST')
->withUrl(new Url('http://example.org/')
->withHeader('Content-Type', 'text/plain');
Run Code Online (Sandbox Code Playgroud)
然后创建了四个副本,但最终结果$request与我简单使用时相同return $this,对吧?
为什么决定保持它不变.那为什么我要做一个clone $this?它有什么好处?
我并没有真正想到这个想法.
我建议你阅读这份文件,其中详细解释了所有的设计选择.
特别是你应该阅读Why value objects?和New instances vs returning $this部分.
关键点如下:
本质上,将HTTP消息建模为值对象可确保消息状态的完整性,并防止对双向依赖性的需求,这种依赖性通常会失去同步或导致调试或性能问题.
和
这些操作也可以使用值对象来完成,具有许多好处:
- 可以存储原始请求状态以供任何消费者检索.
- 可以使用默认标头和/或邮件正文创建默认响应状态.
如果你想深入挖掘,我建议你查看无花果邮件列表的历史(你可以在这里找到),那里有很多关于对象不变性的讨论