これは基本的な OOP の質問だと思います。完全に異なるメッセージ形式がいくつかあるメッセージ パッシング システムを設計していますが、それらすべてを PriorityBlockingQueue に配置できるようにしたいと考えています。最初に考えたのは、 を定義してabstract class Message
から、各メッセージ タイプの Message を拡張するサブクラスを定義することでした。ただし、これは、受信側で、メッセージ プロセッサがメッセージの内容を処理する方法を知るためにサブクラスを識別する必要があることを意味します。そして、私がこれを行う唯一の方法は.instanceof()
orClass.
を使用することであり、どういうわけか正しくないようです。
スコット・マイヤーズが書いているように、
「オブジェクトが T1 型の場合は何かを行い、T2 型の場合は別のことを行う」という形式のコードを書いていることに気付いたときはいつでも、自分を叩いてください。
(彼は続けて、ポリモーフィズムでは、サブクラスごとに異なる実装を持つ同じメソッド名を使用する必要があると主張しています。私の場合、そのアイデアを機能させる方法がわかりません-メッセージタイプ自体はまったく無関係です.)
議論のために、ここに私のメッセージタイプがあります:
- ConsoleObject と ObjectState を識別する ConsoleMessage。
- CardReaderRequestMessage には何も含まれていませんが、単に「次のカード」を要求しています
- byte[80] カード イメージと Last Card インジケータを含む CardReaderMessage
- byte[80] カード画像を含む CardPunchMessage
- CardPunchResponseMessage には、カード イメージがパンチ バッファにコピーされたことを示す以外は何も含まれていません。
私は自分が扱っているメッセージの種類を知る必要があると信じているので、ポリモーフィック メッセージを使用するべきではないと思います。これを適切に設計するにはどうすればよいですか?
===== 編集してフォローアップの質問をする =====
私は、ある時点でそのサブクラスを特定することなく、ポリモーフィック メッセージを使用する方法を見つけようとしていました。提案されたアプローチはprocess()
、各サブクラスでメソッドをオーバーライドすることでした。これが私の(単純化された)抽象メッセージと2つのサブクラスです:
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
}
}
すべての「インバウンド」メッセージに対して、スレッドごとに 1 つのキューがあります。スレッドがコンソールからのメッセージを「再開」するのを待つ必要があるが、その間に他のメッセージ タイプを受信して処理する必要があるとします。
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
}
これは基本的に、「msg」が属するクラスを見つけることを意味します。
私はこれにすべて間違って近づいていますか?「イベント駆動型」モデルでは「待機」はあまり適切ではないことを認識していますが、これは長時間実行されるバックグラウンド ワーカーです。おそらく、process() を使用するという考えは、イベント駆動型スレッドを導く FSM の状態を変更するのにより便利でしょうか?