gpt4 book ai didi

java - 如何在java中创建某种事件框架?

转载 作者:行者123 更新时间:2023-12-02 14:33:49 26 4
gpt4 key购买 nike

我没有 GUI(我的类是 Minecraft Mod 的一部分)。我希望能够模仿 C# 事件框架:一个类声明事件并让其他人订阅它们。

我的第一个方法是创建一个名为 EventArgs 的类,然后执行如下操作:

public class EventArgs
{
public boolean handled;
}

@FunctionalInterface
public interface IEventHandler<TEvtArgs extends EventArgs>
{
public void handle(Object source, TEvtArgs args);
}

public class Event<TEvtArgs extends EventArgs>
{
private final Object owner;
private final LinkedList<IEventHandler<TEvtArgs>> handlers = new LinkedList<>();

public Event(Object owner)
{
this.owner = owner;
}

public void subscribe(IEventHandler<TEvtArgs> handler)
{
handlers.add(handler);
}

public void unsubscribe(IEventHandler<TEvtArgs> handler)
{
while(handlers.remove(handler));
}

public void raise(TEvtArgs args)
{
for(IEventHandler<TEvtArgs> handler : handlers)
{
handler.handle(owner, args);
if(args.handled)
break;
}
}
}

然后一个类会做这样的事情:

public class PropertyChangedEvtArgs extends EventArgs
{
public final Object oldValue;
public final Object newValue;

public PropertyChangedEvtArgs(final Object oldValue, final Object newValue)
{
this.oldValue = oldValue;
this.newValue = newValue;
}
}

public class SomeEventPublisher
{
private int property = 0;
private final Random rnd = new Random();
public final Event<PropertyChangedEvtArgs> PropertyChanged = new Event<>(this);

public void raiseEventOrNot(int value)
{
if(rnd.nextBoolean())//just to represent the fact that the event is not always raised
{
int old = property;
property = value;
PropertyChanged.raise(new PropertyChangedEvtArgs("old(" + old + ")", "new(" + value + ")"));
}
}
}

public class SomeSubscriber
{
private final SomeEventPublisher eventPublisher = new SomeEventPublisher();

public SomeSubscriber()
{
eventPublisher.PropertyChanged.subscribe(this::handlePropertyAChanges);
}

private void handlePropertyAChanges(Object source, PropertyChangedEvtArgs args)
{
System.out.println("old:" + args.oldValue);
System.out.println("new:" + args.newValue + "\n");
}

public void someMethod(int i)
{
eventPublisher.raiseEventOrNot(i);
}
}

public class Main
{
private static final SomeSubscriber subscriber = new SomeSubscriber();

public static void main(String[] args)
{
for(int i = 0; i < 10; ++i)
{
subscriber.someMethod(i);
}
}
}

这种简单方法的最大问题是,它通过将 raise 公开为公共(public)来破坏正确的封装。我看不到解决办法,也许我的整个模式都是错误的。我想要一些想法。

还有一个相关的问题:我希望在引发事件的方法返回后立即引发事件。有没有办法使用线程或其他构造来同步它?当然,调用者代码不能参与同步任务。它必须对它完全透明。

最佳答案

这里最好的做法是避免首先实现您自己的事件框架,而是依赖一些现有的库。开箱即用的 Java 提供 EventListener ,并且至少您可以遵循那里记录的模式。即使对于非 GUI 应用程序,大多数建议也适用。

超越 JDK Guava提供了几种可能的选项,具体取决于您的具体用例。

最有可能的候选者是 EventBus ,其中:

allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other).

或者ListenableFuture (和ListeningExecutorService)其中:

allows you to register callbacks to be executed once [a task submitted to an Executor] is complete, or if the computation is already complete, immediately. This simple addition makes it possible to efficiently support many operations that the basic Future interface cannot support.

或者Service API 其中:

represents an object with an operational state, with methods to start and stop. For example, webservers, RPC servers, and timers can implement the Service interface. Managing the state of services like these, which require proper startup and shutdown management, can be nontrivial, especially if multiple threads or scheduling is involved.

此 API 同样可以让您 register listeners响应您的服务中的状态变化。

即使这些选项都不直接适合您的用例,请查看 Guava's source code有关事件驱动行为和监听器的示例,您可以尝试模拟。

关于java - 如何在java中创建某种事件框架?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38948557/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com