我用Java实现了一个不可变的系统.几乎每个班级都是不可改变的,并且它比我预期的要好得多.
我的问题是尝试发送事件.通常,您有一个事件源和一个事件监听器.源只是保存对侦听器的引用,并在事件发生时发送事件.
但是对于不可变,当您修改字段并创建新对象时,事件侦听器引用会发生更改.所以事件源发送到一些垃圾收集的旧引用.
因此,我的所有GUI类都是可变的,因为它们自然会使用很多事件.但我想找到一种处理事件的优雅方式,这样我就可以使这些事件变得不可变.
编辑:请求的示例代码:
public final class ImmutableButton {
public final String text;
public ImmutableButton(String text) {
this.text = text;
}
protected void onClick() {
// notify listeners somehow,hoping they haven't changed
}
}
public final class ImmutableWindow {
public final ImmutableButton button;
public ImmutableWindow(ImmutableButton button) {
this.button = button;
}
protected void listenForButtonClick() {
// somehow register with button and receive events,despite this object
// being entirely recreated whenever a field changes
}
}
最佳答案
GUI是一种很好的案例,其中可变性更方便,更高效,可用作对象模型.您可以为GUI组件创建一个支持模型,其中的字段已准备好进行读取和写入操作.用户改变显示,该显示被反映到支持模型 – 所有这些都发生在一个对象中.想象一下,每当用户在一个组件上更改某些内容时,必须重新创建一个对象?这肯定会占用你的系统.
原文链接:https://www.f2er.com/java/437446.html虽然缺点是,如果您真的希望GUI对象是不可变的,您可以创建一个全局事件总线来解决侦听器附件问题.通过这种方式,您无需担心将注册事件侦听器的对象实例.事件总线将负责调度事件,监听器注册以及维护它们之间的映射.
这是一个简单的事件总线的草图设计.
public class EventBus {
private Map
编辑
监听器是处理程序 – 它们应该执行业务逻辑而不是保持状态.此外,它们不应该附加到组件.在上面的代码中,侦听器代码必须与ImmutableWindow分离 – 两者都应该独立存在.必须在应用程序启动期间的某处配置ImmutableWindow和ImmutableButton之间的交互(在事件总线中).
您还应该有一个UI组件的中央注册表,它可以通过唯一的ID进行标识,并使用此注册表查找(遍历组件树)组件的最新实例并进行交互.
在实践中,这样的事情……
// The main class. Do the wirings here.
public class App {
@Inject
private EventBus eventBus;
@PostConstruct
public void init() {
ImmutableWindow window = new ImmutableWindow ();
ImmutableButton addButton = new ImmutableButton ();
eventBus.registerEventListener(Events.ADD_BUTTON_CLICKED,new AddButtonClickListener());
}
}
public class AddButtonClickListener implements EventListener {
@Inject
private SomeOtherService someOtherSvc;
@Inject
private UiRegistry uiRegistry;
public void handleEvent(Object... args) {
ImmutableButton addButton = args[0].getSource; // The newset instance of the button must be packed and delivered to the eventlistners when firing an event
ImmutableWindow targetWindow = uiRegistry.lookUp("identifier_of_the_window",ImmutableWindow.class);
// Perform interaction between the two components;
}
}
现在,您拥有完全分离的UI和业务逻辑.您可以随意重新创建组件,监听器不会受到影响,因为它们未附加到任何组件.