客观的
我正在尝试构建一个 MessageDispatcher,它将消息从 3rd 方 API 转换为用户定义的消息,然后将它们分派给用户注册的侦听器。
用户将被期望:
- 为每种类型的用户消息定义一个接口。
- 为每种消息类型向消息调度程序注册一个侦听器。
- 将原始/第 3 方数据传递给消息调度程序。
- 处理传递回侦听器的消息。
问题描述
不幸的是,我似乎无法避免使用原始类型来实现我想要的 API。我在别处读到,使用 Raw 类型没有例外情况,它们仅存在于语言中以实现向后兼容性。
有没有办法可以更改下面的代码以工作,或者我需要重新设计我的 API?
接口
MessageDispatcher 实现以下接口:
public interface MessageDispatcher {
// Register a listener for a given user defined message type.
public <T> void registerListener(
Class<T> messageClass,
MessageListener<T> listener);
// Receive data in 3rd party format, convert and dispatch.
public void onData(Data data);
}
MessageListener 接口定义为:
public interface MessageListener<T> {
public void onMessage(T message);
}
示例用户消息可能如下所示:
public interface MyMessage {
public String getName();
}
注册监听器
用户可以按如下方式注册监听器:
messageDispatcher.registerListener(MyMessage.class,
new MessageListener<MyMessage.class>() {
@Override
public void onMessage(MyMessage message) {
System.out.println("Hello " + message.getName());
}
}
一个标准的消息调度器可能会实现这样的方法:
private Map<Class<?>,MessageListener<?>> messageClassToListenerMap;
public <T> void registerListener(
Class<T> messageClass,
MessageListener<T> listener) {
messageClassToListenerMap.put(messageClass, listener);
// SNIP: Process the messageClass and extract the information needed
// for creating dynamic proxies elsewhere in a proxy factory.
}
发送消息
当 MessageDispatcher 接收到新消息时,它会为该对象创建一个动态代理并将其分派给适当的侦听器。但这就是我的问题所在:
public void onData(Data data) {
// SNIP: Use proxy factory (not shown) to get message class and
// dynamic proxy object appropriate to the 3rd party data.
Class<?> messageClass; // e.g. = MyMessage.class;
Object dynamicProxy; // e.g. = DynamicProxy for MyMessage.class;
// TODO: How to I pick the appropriate MessageListener and dispatch the
// dynamicProxy in a type safe way? See below.
}
如果我尝试使用我无法发送数据的类型:
// Assuming a listener has been registered for the example:
MessageListener<?> listener = messageClassToListenerMap.get(messageClass);
listener.onMessage(dynamicProxy); // ERROR: can't accept Object.
listener.onMessage(messageClass.cast(dynamicProxy); // ERROR: Wrong capture.
这是有道理的,因为我无法知道我的听众接受什么类型的数据以及我正在传递什么类型的数据。
但是,如果我使用原始类型,它可以正常工作:
// Assuming a listener has been registered for the example:
MessageListener listener = messageClassToListenerMap.get(messageClass);
listener.onMessage(dynamicProxy); // OK, provided I always pass the correct type of object.