まず、これをもたらしたライブラリの簡単な説明:
提供されたシリアルポートで継続的にリッスンし、バイトのブロックを読み取り、それらを渡して意味のある方法で処理するライブラリがあります(詳細は質問にとって重要ではありません)。ライブラリをもう少し再利用可能にするために、これらのバイトの処理はインターフェイス (FrameProcessor) に抽象化されました。ライブラリ自体には、それを使用するアプリケーションに関係なく常に発生する処理を処理するためのデフォルトの実装がいくつか存在します。ただし、アプリケーションが特に気にすることを行うために、カスタム プロセッサを追加するためのサポートがあります。
これらのプロセッサに渡されるバイトとは別に、データ オブジェクト (ReceiverData) があります。これには、ほとんどの (すべてであるとは限りません) プロセッサが関心を持つ可能性のある情報が含まれています。ライブラリ自体によって完全に維持されます (つまり、ReceiverData のインスタンスをセットアップ/維持するのはアプリケーションの責任ではありません。データがどのように利用可能になるかを気にする必要はありません。データが利用可能であることだけです)。
現在、ReceiverData はパラメーターとして各プロセッサーに渡されています。
public interface FrameProcessor {
public boolean process(byte[] frame, ReceiverData receiverData);
}
ただし、必ずしもデータを気にしない可能性のあるものにデータを渡す必要があるため、このアプローチは本当に好きではありません。また、ReceiverData を処理するプロセッサの場合、他のメソッド呼び出しでオブジェクト参照を渡す必要があります (これらのメソッド呼び出しがそのデータにアクセスする必要がある場合)。
FrameProcessor を抽象クラスに変更してから、保護された ReceiverData メンバーのセッターを定義することを検討しました。しかし、それはちょっとひどいようにも思えます - すべての FrameProcessors のリストを反復処理し、ReceiverData インスタンスを設定する必要があります。
また、ある種の静的なスレッド化されたコンテキスト オブジェクトについても考えました (ライブラリは一度に複数のポートでのリッスンをサポートしているため、必然的にスレッド化されます)。基本的に、次のようなものがあります。
public class ThreadedContext {
private static Map<Long, ReceiverData> receiverData;
static {
receiverData = new HashMap<Long, ReceiverData>();
}
public static ReceiverData get() {
return receiverData.get(Thread.currentThread().getId());
}
public static void put(ReceiverData data) {
receiverData.put(Thread.currentThread().getId(), data);
}
}
こうすることで、ライブラリ内の各スレッドが開始されたときに、その ReceiverData への参照を ThreadedContext に追加するだけで済み、必要に応じてプロセッサがそれを渡す必要なく利用できるようになります。
私はすでにうまく機能する解決策を持っているので、これは確かに衒学的な質問です。それはちょうど私を悩ませました。考え?より良いアプローチ?