我确信这是一个基本的 OOP 问题——我正在设计一个消息传递系统,其中有几种完全不同的消息格式,但我希望它们都能够放在 PriorityBlockingQueue 上。我的第一个想法是abstract class Message
为每种消息类型定义一个然后定义扩展 Message 的子类。但这意味着,在接收端,消息处理器需要识别子类才能知道如何处理消息的内容。我知道这样做的唯一方法是使用.instanceof()
orClass.
并且它似乎不正确。
正如斯科特迈耶斯所写,
任何时候你发现自己在编写“如果对象是 T1 类型,则做某事,但如果它是 T2 类型,则做其他事情”形式的代码,给自己一记耳光。
(他继续指出,在多态中,你应该有相同的方法名称,每个子类有不同的实现。我不明白如何让这个想法在我的情况下发挥作用——消息类型本身是完全不相关的.)
为了讨论,这里是我的消息类型:
- ConsoleMessage,标识一个 ConsoleObject 和一个 ObjectState。
- CardReaderRequestMessage,不包含任何内容,只是请求“下一张卡片”
- CardReaderMessage,包含一个 byte[80] 的卡片图像和一个 Last Card 指示符
- CardPunchMessage,包含一个byte[80]的卡片图片
- CardPunchResponseMessage,不包含任何内容,但表示卡片图像已复制到打孔缓冲区
我相信我必须知道我正在处理什么样的消息,所以我怀疑我不应该使用多态消息。我应该如何正确设计这个?
===== 编辑提出后续问题 =====
我试图找到一种方法来使用多态消息,而不必在某些时候识别它的子类。建议的方法是覆盖process()
每个子类中的方法。这是我的(简化的)抽象 Message 和两个子类:
public abstract class Message {
public abstract void process() {
// subclasses of Message implement this
}
public static class ConsoleMessage extends Message {
private int obj;
private int state;
public ConsoleMessage(int x, int y) {
obj = x;
state = y;
}
@Override
public void process() {
// do something with obj and state?
}
public static class CardReaderMessage extends Message {
private byte[] card;
private boolean lastCardIndicator;
public CardReaderMessage(byte[] c, boolean lc) {
card = c;
lastCardIndicator = lc;
}
@Override
public void process() {
// do something with card and lastCardIndicator
}
}
对于所有“入站”消息,每个线程都有一个队列。假设我的线程需要等待来自控制台的消息“恢复”,但同时应该接收和处理其他消息类型:
waitForResumeMessage() {
while (true) { // the following will block until a msg arrives
Message msg = inboundMessageQueue.receiveMessage();
msg.process();
但现在呢?process() 的某些实现已将一些数据移动到某处,但最终我需要能够编写:
if // msg was ConsoleMessage "resume" command
return; // .. from waitForResumeMessage()
} // else iterate until another message
}
这基本上意味着找出“味精”属于哪个类。
我接近这一切都错了吗?我意识到“等待”在“事件驱动”模型中并不合适,但这是一个长期运行的后台工作者。也许使用 process() 的想法对于更改引导事件驱动线程的 FSM 的状态更有用?