First, a brief description of the library that brought this up:
I have a library that listens continuously on a provided serial port, reading in blocks of bytes and passing them along to be processed in some meaningful way (details aren't important to the question). To make the library a bit more reusable, processing these bytes was abstracted out to an interface (FrameProcessor). A few default implementations exist in the library itself to handle processing that's always going to occur regardless of the application using it. However, there's support for adding in custom processors to do things the application specifically cares about.
Aside from the bytes being passed to these processors, there's a data object (ReceiverData) that contains information that most (but not guaranteed to be all) of the processors might find interesting. It's maintained entirely by the library itself (i.e. it isn't the responsibility of the application to setup/maintain any instances of ReceiverData. They shouldn't have to care how the data is made available, just that it is available).
Right now, ReceiverData is being passed as a parameter to each processor:
public interface FrameProcessor {
public boolean process(byte[] frame, ReceiverData receiverData);
}
However, I really don't like this approach, as it's requiring data to be passed to something that might not necessarily care about it. Also, for the processors that do care about ReceiverData, they've got to pass the object reference around in whatever other method calls they make (provided those method calls need to access that data).
I've considered changing the FrameProcessor to an abstract class and then defining a setter for a protected ReceiverData member. But that seems kind of gross as well - having to iterate over the list of all FrameProcessors and setting the ReceiverData instance.
I've also thought about some kind of static threaded context object(necessarily threaded since the library supports listening on multiple ports at once). Essentially, you'd have something like the following:
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);
}
}
That way, when each thread in the library started, it could just add a reference to its ReceiverData to ThreadedContext, which would then be available as needed to the processors without needing to pass it around.
This is certainly a pedantic question, as I've already got a solution that works fine. It just bothered me. Thoughts? Better approaches?
I like your current approach the best. It's inherently thread-safe (because stateless). It allows for the same processor to be used by multiple threads. It's easy to understand and use. It's very similar to, for example, the way a servlet works: the request and the response objects are passed to the servlet, even if they don't care about them. And it's also very easy to unit test, because you don't have to setup a thread-local context to be able to test a processor. You just pass a ReceiverData (real or fake), and that's it.
You could, instead of passing a byte array and a ReceiverData, mix both in a single argument.