Java 不可变对象之间的事件处理

Java 不可变对象之间的事件处理,java,immutability,fluid,Java,Immutability,Fluid,我正在用Java制作一个简单的记事本应用程序,并尝试使用一种流动的、不变的样式,以便进行尝试。我发现这很有趣,并且看到了很多关于函数式编程(代码清晰性等)的优点 但我对一般的事件处理有一个问题。我有一个类TextArea,它提供了一个像记事本一样的文档。然后我有另一个类滚动条。它们是由一个主类CentralController操纵的,它使滚动条和文本区域保持在一起工作(不是真正的类名,只是在本例中) 因此,如果用户按下向下箭头,CentralController只调用TextArea.withD

我正在用Java制作一个简单的记事本应用程序,并尝试使用一种流动的、不变的样式,以便进行尝试。我发现这很有趣,并且看到了很多关于函数式编程(代码清晰性等)的优点

但我对一般的事件处理有一个问题。我有一个类TextArea,它提供了一个像记事本一样的文档。然后我有另一个类滚动条。它们是由一个主类CentralController操纵的,它使滚动条和文本区域保持在一起工作(不是真正的类名,只是在本例中)

因此,如果用户按下向下箭头,CentralController只调用TextArea.withDownArrow(),并在光标向下移动时返回TextArea的新副本。问题是滚动条现在需要移动,因此中央控制器需要知道文本区域是否被向下箭头滚动

我第一次尝试解决它是返回一个对象,该对象不仅包含新的TextArea,而且还包含一个标志,表明滚动是否需要更新。这很管用,但感觉不太对,因为我不再返回TextArea,而你真的应该返回“适当”的函数编程(粗略地说)

因此,我尝试在TextArea内设置一个标志,如果TextArea.withDownArrow()导致滚动,则会设置该标志。这也很有效,但将方法结果“全局”存储在类中似乎是错误的。它还存在以下问题:您可能会使用downarrow()调用两次,然后该标志会被新结果覆盖

我读过一些关于反应式编程的书,它看起来确实很有趣,但我不确定它是否适合这种情况,即“child”类向兄弟姐妹发送消息

我只是想补充一句,我的印象是,在这种情况下,正常的事件处理是行不通的。对于不可变对象,当您更改某些内容时,您将创建一个新对象。因此,任何试图向侦听器发送事件的对象都将发送到旧指针

我是否因为感觉自己是这样而错过了一个显而易见的方法?或者使用普通的Java事件处理技术真的可以吗?我什么都不担心

编辑:我想我现在已经找到了一个足够好的解决方案。即使接收事件的类(滚动条)一直被重新创建,该类的成员也不会被重新创建。只有改变的东西

所以我将在ScrollBar中有一个简单的事件接收器方法,TextArea可以有一个监听器列表(基本上是用监听器执行事件的“正常”方式)


总之,我的错误是认为需要将事件发送到实例,而不是该实例的成员

您必须区分值对象和逻辑对象。值对象只包含值,不包含逻辑(*)。它们可以是不变的

当然,文本区域不能是值对象,滚动条也不能是值对象,因为它们必须包含逻辑。它们也不能是不变的,因为它们包含状态。所以,擦掉所有这些。这行不通


(*)或者至少没有处理外部实体的逻辑,或者操纵它们自己的任何状态。

不过,为了澄清,每次修改我都会返回一个全新的文本区域。目前一切都运行得相当好(表现也很好),但我对这些事件尤其不满意。此外,这些对象是我的“纯”模型的一部分,实际的屏幕绘制方法在别处,只是查看模型并渲染它。