Java 公开远程接口或对象模型

Java 公开远程接口或对象模型,java,eclipse,osgi,oop,Java,Eclipse,Osgi,Oop,我有一个关于公开异步远程接口的最佳方法的问题 条件如下: 协议是异步的 第三方可以随时修改数据 命令往返可能非常重要 该模型应该非常适合UI交互 协议支持对特定对象的查询,模型也必须支持 为了提高我在这方面的技能(并复习我的Java),我已经开始创建一个基于Eclipse的前端(如下所述) 所以问题是,;我应该如何将远程接口公开为整洁的数据模型(在本例中是跟踪管理和事件处理) 我欢迎从一般讨论到模式名称删除或具体示例和补丁的任何内容:) 我在这里的主要目标是从总体上了解这类问题。如果我的项

我有一个关于公开异步远程接口的最佳方法的问题

条件如下:

  • 协议是异步的
  • 第三方可以随时修改数据
  • 命令往返可能非常重要
  • 该模型应该非常适合UI交互
  • 协议支持对特定对象的查询,模型也必须支持
为了提高我在这方面的技能(并复习我的Java),我已经开始创建一个基于Eclipse的前端(如下所述)

所以问题是,;我应该如何将远程接口公开为整洁的数据模型(在本例中是跟踪管理和事件处理)

我欢迎从一般讨论到模式名称删除或具体示例和补丁的任何内容:)


我在这里的主要目标是从总体上了解这类问题。如果我的项目可以从中获益,那很好,但我严格地展示它是为了让大家开始讨论

我已经实现了一个我调用的协议抽象(出于遗留原因),它允许我使用方法调用来访问大多数公开的特性,我很乐意使用方法调用,即使它还远远不够完美

xmms2守护进程提供的功能包括曲目搜索、元数据检索和操作、更改播放状态、加载播放列表等

我正在更新XMMS2最新的稳定版本,我想我还可以修复我当前实现的一些明显的弱点。 我的计划是在协议接口之上构建一个更好的抽象,允许与守护进程进行更自然的交互。当前的实现很难使用,坦率地说相当丑陋(更不用说真正可怕的UI代码了)

今天,我有了一个接口,我可以使用该接口根据类的id获取类的实例。搜索是通过接口(不幸的名称空间冲突)执行的,我想我宁愿移动到跟踪

任何数据都可以由第三方在任何时候进行修改,这应该适当地反映在分发的模型和更改通知中

这些接口在连接时通过返回如下所示的对象层次结构而公开:

  • 联系
    • 播放getPlayback()
      • 播放、暂停、跳跃、当前曲目等
      • 公开播放状态更改
    • 跟踪跟踪跟踪()
      • 轨道(id)等
      • 公开曲目更新
    • 集合getCollection()
      • 加载和操作播放列表或命名集合
      • 查询媒体库
      • 公开集合更新

对于异步位,我建议检查
java.util.concurrent
,尤其是
未来
接口。future接口用于表示尚未准备好但正在单独线程中创建的对象。您说第三方可以随时修改对象,但我仍然建议您在这里使用不可变的返回对象,并使用一个单独的线程/事件日志,您可以在对象过期时订阅以引起注意。我很少使用UI编程,但我相信使用异步调用的未来将使您拥有一个响应良好的GUI,而不是一个等待服务器回复的GUI

对于查询,我建议使用方法链接来构建查询对象,方法链接返回的每个对象都应该是
Iterable
。类似于Djangos模型。假设您有
QuerySet
,它实现了
Iterable
。然后可以调用
allSongs()
,这将返回一个遍历所有歌曲的结果。或者
allSongs().artist(“披头士”)
,您将拥有一个覆盖所有Betles歌曲的iterable。甚至
allSongs().artist(“披头士”).years(19651967)
等等

希望这能作为一个起点有所帮助。

@:非常感谢

使用Future进行异步操作是很有趣的。唯一的缺点是它不提供回调。但是,我又一次尝试了这种方法,看看我是怎么做到的:)

我目前正在解决一个类似的问题,使用一个工作线程和一个阻塞队列来调度传入的命令回复,但是这种方法并没有很好地转换

远程对象可以修改,但由于我使用线程,所以我尝试保持对象不变。我目前的假设是,我将在表单上发送跟踪更新的通知事件

somehandlername(int changes, Track old_track, Track new_track)
或者类似的,但是我可能会得到同一首歌的几个版本

我肯定会研究Djangos方法链接。我一直在研究一些类似的构造,但没有找到一个好的变体。返回一些iterable是很有趣的,但是查询可能需要一些时间才能完成,我不想在完全构造查询之前实际执行查询

也许像

Tracks.allSongs().artist("Beatles").years(1965,1967).execute()

返回未来可能有效…

Iterable只有迭代器get()或类似的方法。因此,在实际开始迭代之前,不需要构建任何查询或执行任何代码。它确实使示例中的execute变得多余。但是,线程将被锁定直到第一个结果可用,所以您可以考虑使用执行器在单独的线程中运行查询的代码。

@ /P> 这当然是可能的,但正如您所注意到的,这会使它阻塞(由于磁盘休眠,在家中大约10秒钟),这意味着我无法使用它直接更新UI

我可以使用迭代器在一个单独的线程中创建结果的副本,然后将其发送到UI,但尽管迭代器解决方案本身相当优雅,但它并不适合。最后,需要实现一些东西
class Track {
    public final String album;
    public final String artist;
    public final String title;
    public final String genre;
    public final String comment;

    public final String cover_id;

    public final long duration;
    public final long bitrate;
    public final long samplerate;
    public final long id;
    public final Date date;

    /* Some more stuff here */
}
interface TrackUpdateListener {
    void trackUpdate(Track oldTrack, Track newTrack);
}
interface TrackQuery extends Iterable<Track> {
    TrackQuery years(int from, int to);
    TrackQuery artist(String name);
    TrackQuery album(String name);
    TrackQuery id(long id);
    TrackQuery ids(long id[]);

    Future<Track[]> get();
}
tracks.allTracks();
tracks.allTracks().artist("Front 242").album("Tyranny (For You)");
interface Tracks {
    TrackQuery allTracks();

    void addUpdateListener(TrackUpdateListener listener);
    void removeUpdateListener(TrackUpdateListener listener);
}