我在设计一个干净的解决方案以使用观察者模式样式解决方案发送不同类型的消息时遇到问题。
我有一个客户端应用程序通过 tcp 套接字连接到服务器(我无法更改)。我可以发送和接收 json 编码的消息,这些消息将始终包含一个“msg”参数,该参数定义它是什么类型的消息。另请注意,我可以接收发送给多个客户且我自己的客户未请求的消息(例如,如果有人发送聊天消息)。
示例:连接时我收到{"msg":"ServerInfo","version":"1.0a"}
发送{"msg":"Ping"}
回复{"msg":"Ping","time":1381358623}
我可以随时{"msg":"Chat", "from":"Person", "text":"Hello everyone"}
收到
一些消息更复杂,可以有嵌套对象,例如
{
"msg":"SampleData",
"people":[{
"name":"Joe"
"age":25
},{
"name":"Bob",
"age":30
}]
}
有几十种不同类型的消息,它们都具有不同数量和类型的字段。
我目前有一个类,负责监听套接字并使用 Gson 将所有消息解析到只有“msg”参数的“BasicMessage”类中。我有一个 Map 将所有消息类型字符串映射到它们各自的类。一旦我有了“msg”参数,我就可以查找我需要用 Gson 反序列化它的类,然后这样做。现在我有一个正确类的实例,但这就是我的设计开始崩溃的地方。
我希望其他各种类能够仅订阅几种类型的消息。问题是我似乎无法找到一种方法来做到这一点,而不需要一堆 instanceof 或在每个客户端中重新解析所有内容。
我最初的想法是使用像这样的参数化接口:
public interface MessageListener<T> {
public void onReceivedMessage(T message);
}
然后在反序列化消息的类中,我有一个List<MessageListener<Message>>
Message 是每个其他 Message 继承自的抽象类。然后我遇到了MessageListener<SpecificMessage>
不继承的类型擦除问题,MessageListener<Message>
所以我没有办法将客户端添加到一个简单的列表中。似乎我必须为每种类型的消息都有一个列表,这也不理想。这种设计的另一个问题是它会限制我只对一个需要多个消息的类中的各种消息侦听器使用匿名内部类,因为即使你用不同的类参数化它,你也不能两次实现相同的接口.
有没有更好的模式可以用于这种情况?我觉得我可能不得不使用反射来让它“整齐”地工作。理想情况下,如果我想添加另一种消息类型,我希望它只需要添加要反序列化的类,也许还需要从其 msg 字符串到该类的映射,然后能够开始为该类型的消息添加侦听器另一个班级。
提前致谢!