J
John C. Bollinger
Oliver said:Okay, here's the next situation I've concocted where I can't figure out
how to implement it without using statics. Let's say you have some sort of
hardware hooked up to your computer (e.g. a webcam, atom decay-sensor,
joystick, etc.) and you want a class to act as an abstraction of that
hardware. Since you only have one copy of that hardware, you'd like to
ensure only one instance of that class binds to the hardware (assume
something disastrous happens if two instances tries to bind to the same
hardware). Can you design a robust class library for this without using
statics?
The underlying question being what would I use instead of the
much-overused Singleton pattern? I pretty much universally prefer the
"Just Use One" strategy over the Singleton pattern, even without
consideration of implementation details such as static members. There
are a number of ways to "Just Use One", but they all boil down to
passing around a reference to some object from which you can obtain a
reference to the designated instance. In some cases you might be able
to use inner/containing class relationships instead of passing around
explicit references.
You will no doubt observe that so far I have sidestepped the main thrust
of your question. In part this is because I see it as based on a
largely artificial requirement (to *ensure* that only one instance binds
to the hardware). It is often entirely sufficient to simply say "don't
do that". That's especially so when you can't programmatically *ensure*
compliance, which is the case here. Static class members avail nothing
if a different copy of the class is loaded via a different classloader
or in a different VM. Or if other code, possibly in an unrelated piece
of software, interacts with the hardware independently of the
hypothetical Java class library.
With that said, the Factory pattern is the usual fall back for all
questions of controlling and/or monitoring the creation of objects. Its
specific application to the problem you raise might take the form of a
factory implementation that maintains an internal map from hardware
identifiers to interface objects, and uses it to always provide the same
interface object in response to all requests for interfaces to the same
hardware.