方案
我会尽可能简洁。基本上参考这个classdiag,我有一个管理 SocketManager (管理一个Socket连接)列表的外观。每个 SocketManager 使用唯一的 SocketUserId 登录到远程服务器。此外,每个 SocketManager 都会接受来自客户的邮件,这些邮件的目的地是收件人的特定列表。为了便于讨论,请将这些 Receipients 简单地视为由名称标识的远程数据存储区。
客户端将发送如下数据:
SocketFacade facade = ...;
byte[] data = ...
facade.sendData( receipient, data );
当 SocketFacade 启动时,它将查询一个mysql表,该表返回 SocketUserId 和 Receipients 之间的1-m关系。我将使用MultiValuedMap来表示这种1米的关系。然后通过迭代地图启动多个 SocketManager 。
(1) Map< SocketUserId, List<Receipient> >
e.g。假设我们有2个 SocketManager ,其中 SocketUserId s“alice”&amp; “汤姆”分别
+----SocketManager1 ( "alice" ) for Receipients { "B", "C" }
|
SocketFacade
|
+----SocketManager2 ( "tom" ) for Receipients { "A", "D" }
问题
我正在讨论如何实现 sendData 方法。基本上我需要一种方法从收据(例如“B”)映射到其负责的 SocketManager (例如 SocketManager1 )。
让我们假设我这样做
(2) Map< SocketUserId, SocketManager >
(3) Map< Receipient, SocketUserId >
SocketFacade 还支持会改变由(1)表示的关系的方法。如果我写入数据库,则(1),(2)和&amp ;;中的内存数据结构。 (3)需要同步改变。 SocketFacade 也必须是线程安全的。最初的想法是拥有某种发布订阅系统,通过这种系统,添加/删除数据库将导致更改通过回调传播。
interface Callback
{
void receipientAdded( Receipient r );
void receipientDeleted( Receipient r );
}
答案 0 :(得分:1)
在每个SocketManager
中保留对Receipient
的引用。这样,您可以避免映射(需要更多RAM,速度较慢且不添加任何值)。
在SocketManager
中,保留Receipient
的列表。在添加和删除Receipient
时,请更新指向SocketManager
。
在SocketFacade
中,您需要一张获取SocketUserId
并返回SocketManager
的地图。通过查询地图中的ID来填充该地图。存在所有管理员后,将收件人添加到每个管理员。这需要两个SQL查询。
使用任何ORM工具都很容易映射。
答案 1 :(得分:1)
由于SocketUserId和SocketManager之间有1-1关系,你不能只在SocketMananger中添加对SocketUserId的引用,并在收件人中添加对SocketManager的引用吗?
然后你会在你的正面有一个包含收件人的Map和SocketManager列表。在sendData
函数中,您将从映射中获取收件人,并从此收件人获取对其SocketManager的引用。
问候
纪尧姆
答案 2 :(得分:1)
在抽象级别,您有:1 Thing
与n OtherThing
相关。您可以通过创建一个特殊关系对象来对此进行建模,该对象引用Thing
并包含对java.util.List<OtherThing>
s的OtherThing
个引用。这使您的域对象(Things)整洁有关系信息。但是如果它看似正确,那么将java.util.List
直接添加到类Thing
(或子类)就更简单了。只有在需要建立关系时,List变量才能保留为空并填充java.util.ArrayList<OtherThing>
。