如何在java中创建某种类型的事件框架?

如何在java中创建某种类型的事件框架?,java,events,method-reference,Java,Events,Method Reference,我没有GUI(我的类是Minecraft Mod的一部分)。我希望能够模拟C#event框架:一个类声明事件并让其他人订阅它们 我的第一种方法是创建一个名为EventArgs的类,然后执行如下操作: public class EventArgs { public boolean handled; } @FunctionalInterface public interface IEventHandler<TEvtArgs extends EventArgs> { pu

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

我的第一种方法是创建一个名为
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);
        }
    }
}
公共类事件参数
{
公共服务;
}
@功能接口
公共接口IEventHandler
{
公共无效句柄(对象源,TEvtArgs args);
}
公开课活动
{
私有最终客体所有者;
private final LinkedList handlers=new LinkedList();
公共事件(对象所有者)
{
this.owner=所有者;
}
公共无效订阅(IEventHandler处理程序)
{
添加(handler);
}
公共无效取消订阅(IEventHandler处理程序)
{
while(handlers.remove(handler));
}
公共无效提升(TEvtArgs args)
{
for(IEventHandler处理程序:处理程序)
{
handler.handle(所有者,参数);
如果(参数已处理)
打破
}
}
}
然后一个类将执行如下操作:

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);
        }
    }
}
public类PropertyChangedEvtArgs扩展了EventArgs
{
公共最终目的价值;
公共最终目的价值;
公共属性changedevtargs(最终对象oldValue,最终对象newValue)
{
this.oldValue=oldValue;
this.newValue=newValue;
}
}
公共类SomeEventPublisher
{
私有int属性=0;
私有最终随机rnd=新随机();
公共最终事件属性更改=新事件(此);
public void raiseEventOrNot(int值)
{
if(rnd.nextBoolean())//仅表示事件并不总是引发的事实
{
int old=财产;
财产=价值;
PropertyChanged.raise(新的propertychangedevtags(“旧的”(“+old+”),“新的”(+value+”));
}                
}
}
公共类订阅服务器
{
私有最终SomeEventPublisher eventPublisher=新SomeEventPublisher();
公共用户()
{
eventPublisher.PropertyChanged.subscribe(this::HandlePropertyChanges);
}
私有void HandlePropertyChanges(对象源,PropertyChangedEvtArgs args)
{
System.out.println(“old:+args.oldValue”);
System.out.println(“新建:+args.newValue+”\n);
}
公共方法(int i)
{
eventPublisher.raiseEventOrNot(i);
}
}
公共班机
{
私有静态最终SomeSubscriber=new SomeSubscriber();
公共静态void main(字符串[]args)
{
对于(int i=0;i<10;++i)
{
方法(i);
}
}
}
这种天真方法的最大问题是,它将
raise
公开,从而破坏了正确的封装。我找不到解决的办法,也许我的整个模式都错了。我想要一些想法


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

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

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

最有可能的候选人是:

允许在组件之间进行发布-订阅样式的通信,而无需组件彼此显式注册(从而相互了解)

或者(和
ListingExecutorService
),其中:

允许您在[提交给
执行者的任务完成后,或者如果计算已经完成,则立即注册要执行的回调。这个简单的添加使得能够有效地支持未来基本接口无法支持的许多操作

或API,其中:

表示具有操作状态的对象,以及要启动和停止的方法。例如,Web服务器、RPC服务器和计时器可以实现服务接口。管理此类服务的状态(需要正确的启动和关闭管理)可能非常重要,特别是在涉及多个线程或调度的情况下

此API同样允许您响应服务中的状态更改

即使这些选项都不直接适用于您的用例,也请查看事件驱动行为和侦听器的示例,您可以尝试模拟它们