16

我经常听到术语“无状态”和“不可变”。例如,HTTP 是无状态协议,String 对象是不可变对象。但我很难理解两者之间的区别。当我创建一个无状态对象时,它不会在内部存储任何“状态”数据。如果我创建一个不可变对象,则意味着它永远不会改变。

这不是同一个意思吗?

由于不可变对象不会改变,根据定义它不能有状态。这就是它永远的样子。如果一个对象没有状态,它就不能被改变(根据定义)。因此,不是所有的无状态对象都是不可变的和不可变的对象是无状态的吗?

什么是可变无状态对象或不可变有状态对象的示例?

4

4 回答 4

8

上下文很重要,这里有两个不相关的概念。

“HTTP 是一种无状态协议”意味着每个请求对其他请求没有隐含的了解,包括同一客户端发送的任何先前请求。这与建立连接然后发送不同命令的 FTP 或 SMTP 等协议不同——每个命令/请求都与同一个客户端/连接“关联”。当然状态/跟踪是通过添加回来的。cookie 和跟踪 URI,甚至是流水线——但关键是每个请求在 HTTP 协议中都是“新的”和“独立的”。

“字符串是一个不可变的对象”意味着该特定对象的数据将始终与它现在在每种可观察方式中的数据相同(这也意味着不可更改的可观察属性)。一些纯粹主义者可能会争辩说它具有比这更深层次的含义,但实际上是关于可观察属性 - 当不可变对象可以“包含”可变对象时,问题变得更加复杂。

(是的,从技术上讲,没有允许的数据或状态的对象无法更新,因此是“不可变的”。然而,再一次,上下文很重要,谈论大象或树干上的尖牙很奇怪在老虎身上。)

编辑:两者之间的区别

没有状态的对象是无状态的。所有无状态对象都是不可变的(因为没有什么可以改变的);这是一个重言式的技术性。一个对象可以有状态并且仍然是不可变的——但是,一个有状态(不可变或其他)的对象不能再被认为是无状态的。根据对链接答案的评论:“[一个不可变对象]只有一个状态”,即初始状态。

——来自我的评论

于 2012-10-19T19:13:18.867 回答
6

不,它们的意思不同。

不可变对象永远不会改变。这并不意味着该对象中包含的数据不能指示状态。它只是意味着如果你想表示状态的变化,你需要创建一个新的对象。

无状态意味着没有状态。

于 2012-10-19T19:12:40.677 回答
3

我会说在某些情况下这是同一件事,但我们关注的方面略有不同。

当人们说“无状态”意味着它没有状态时,这让我发笑。当然,从某种角度来看,它有一些状态,例如,无状态服务可以由复杂的对象图(依赖注入)支持。问题是网络协议对“状态”的含义略有不同:它取决于先前的请求/响应。但是根据定义,不可变服务也不依赖于先前的调用。

“无状态”并不总是与 HTTP 协议相关,我们可以使用同一个术语来争论您闪亮的 OOP 代码中服务对象中的设置器。在这里您可以看到这两个术语实际上是相同的:不可变服务是无状态服务,反之亦然。

但是,将值对象称为“无状态对象”对我来说很尴尬。听起来很可怕。

回顾:如果是服务(网络或 OOP,没关系),我会说这些术语是可以互换的。

举个例子:

interface Logger
{
    public function logWarning(string $message);
    public function logError(string $message);
}

我们调用了多少次logWarninglogError调用的顺序也无关紧要。因此,我们可以称之为“无状态服务”。

但是这个服务也没有设置器和任何修改器,比如changeFileName()-> 它是一个不可变的服务/对象。

可变性使对象有状态。有状态使对象可变。这些术语在服务上下文中是相互依赖的。

于 2017-01-04T11:32:26.300 回答
1

它们绝对不一样。

不可变对象是永远不会改变的。不可变对象的状态永远不会被修改,不可变对象的别名是无害的,不可变对象不需要别名控制,尽管可能需要别名控制来证明对象实际上是不可变的。

无状态意味着没有状态。HTTP 被称为无状态协议,因为每个命令都是独立执行的,而不知道它之前的命令。它基于请求范例。在此协议中,通信通常通过 TCP/IP 协议进行。

于 2012-10-19T19:17:11.233 回答