假设我们有一个基类消息:
public abstract Class Message {
Object content;
public Message(Object content) {
this.content = content;
}
}
各种实施:
public Class Packet extends Message {
public Packet(Long largeNumber) {
super(largeNumber);
}
public Long unpack() {
return (Long) content;
}
}
public Class Letter extends Message {
public Letter(Short smallNumber) {
super(smallNumber);
}
public Short unpack() {
return (Short) content;
}
}
现在假设我们有一个发送者类,它会在某处发送消息。
public Class Sender {
public send(Message msg) {
// send it somewhere
}
}
接收器类,接收消息:
public Class Receiver {
receive(Message msg) {
// do something with the msg
}
}
然而,接收器类只获取超级类消息并且事先不知道它将接收哪个子类。那么我现在如何解开"消息?
如果我们假设我确切知道哪些消息会落在哪里,我可以像这样使用向下转发:
Packet packet = (Packet) msg;
但不知何故,这种感觉是错误的,因为它首先解释了多态性的观点。发送绝对子消息会更好吗? 或者是否有解决方案我不会看到这样的问题(例如在某些变体中使用泛型 - 我对它们不太熟悉)?
答案 0 :(得分:3)
可以使用visitor pattern:
通过邮件本身解压缩邮件public abstract Class Message {
void send(Receiver r) {
r.receive(this); // Catch-all
}
}
public Class Packet extends Message {
void send(Receiver r) {
r.receive(this); // Overload for packets
}
}
public Class Letter extends Message {
void send(Receiver r) {
r.receive(this); // Overload for letters
}
}
public Class Receiver {
// There is an overload for each subclass
receive(Packet packet) {
}
receive(Letter letter) {
}
// This is the catch-all implementation
receive(Message msg) {
}
}
这种方法允许接收器在静态类型的上下文中单独处理字母和数据包。 Catch-all实现通常用于错误报告。
答案 1 :(得分:1)
可行的方法是泛型:
public abstract class Message<T> {
private T content;
public T unpack() {
return content;
}
}
答案 2 :(得分:0)
如果要使用polimorfism属性,则必须在父类Message中声明抽象方法unpack,然后在派生类中覆盖它:
public abstract class Message {
public abstract String unpack();
// other code
}
public class Letter extends Message {
public String unpack() {
// your unpacked code
}
}
public class Receiver{
receive(Message msg){
String s = msg.unpack();
/* you can invoke unpack method because earlier declared it as abstract in parent class */
}
}
答案 3 :(得分:0)
我建议为每种类型的Message创建一个处理程序映射。 消息的内容不应该丢失其类型。消息和信件的例子:
abstract class Message<T> {
private T content;
protected Message(T content) {
this.content = content;
}
public T getContent() {
return content;
}
}
class Letter extends Message<Short> {
public Letter(Short number) {
super(number);
}
}
然后为处理程序创建一个接口:
interface MessageHandler<T extends Message> {
void handle(T message);
}
然后创建一些“提供者”来存储所有处理程序:
class MessageHandlersProvider {
Map<Class<? extends Message>, MessageHandler<? extends Message>> handlers = new HashMap<>();
<T extends Message> void addHandler(Class<T> messageType, MessageHandler<T> handler) {
handlers.put(messageType, handler);
}
MessageHandler<?> getHandler(Class<? extends Message> messageType) {
return handlers.get(messageType);
}
}
处理程序的示例:
class LetterHandler implements MessageHandler<Letter> {
@Override
public void handle(Letter letter) {
//Short number = letter.getContent();
//do anything
}
}
现在您可以创建一个提供程序并由处理程序以这种方式填充它:
MessageHandlersProvider handlersProvider = new MessageHandlersProvider();
handlersProvider.addHandler(Letter.class, new LetterHandler());
然后获取处理程序并处理任何类型的消息:
MessageHandler<?> handler = handlersProvider.getHandler(message.getClass());
handler.handle(message);
通过通用方法addHandler填充地图非常重要。它确保您没有为错误类型的Message添加处理程序。
我知道它在最后一行打破了泛型,但它似乎非常安全,因为我们保证不会放置和使用错误的处理程序。