java – 不可变事件处理

前端之家收集整理的这篇文章主要介绍了java – 不可变事件处理前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我用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组件创建一个支持模型,其中的字段已准备好进行读取和写入操作.用户改变显示,该显示被反映到支持模型 – 所有这些都发生在一个对象中.想象一下,每当用户在一个组件上更改某些内容时,必须重新创建一个对象?这肯定会占用你的系统.

虽然缺点是,如果您真的希望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和业务逻辑.您可以随意重新创建组件,监听器不会受到影响,因为它们未附加到任何组件.

猜你在找的Java相关文章