In cases like this it's important to ensure that you keep your class space as wide as pos-
sible. If three implementations of this API were present in the runtime, then clients
would only be able to use one implementation at a time, determined by the API pack-
age they're wired to, making the other two implementations redundant. Clearly this
Do you remember learning about shadowing (section 5.1.2)? In your current predica-
ment, shadowing becomes useful. If your bundles both import and export the API
packages, then the runtime will play a clever trick. If the API packages aren't already
available when your bundle is resolved, then the import statement is ignored and the
API packages are exported from your bundle. If the API packages are available, then the
export statement is ignored and the API packages are imported into your bundle. This
arrangement means that there will only be one instance of the API package available
in the framework, shared between all of the implementations. This means that clients
can use any of the implementations.
If dependencies are only on interfaces, to the point where implementations can be
swapped in and out at will, how does anything get hold of concrete instances of these
interfaces? If you're thinking in terms of conventional Java, you probably already have
an answer ready—the factory pattern.
Avoid static factory classes
The factory pattern is extremely prevalent in Java; static factories are used to provide
indirection between interfaces and implementations. Although this pattern is techni-
cally possible in OSG i, it's unable to cope with OSG i's dynamism. If you do create an
object using a static factory, then you won't get any notification when the bundle that
provided it is stopped or even uninstalled. What's worse is that because the static fac-
tory is unlikely to be OSG i aware, it won't be tracking its dependencies either. This
means that watching the lifecycle of the bundle that hosts the static factory isn't always
good enough to tell you that your object has become invalid.
The ability to register for Service Registry event notifications as well as the Service
Registry's get/release semantics provide exactly the lifecycle structure that's missing
from the static factory model. If you had used static factories to build your superstore,
then you wouldn't be able to dynamically add and remove special offers. What's worse,
you wouldn't have been able to prevent people from seeing the special offer even if
you removed the department, causing failures elsewhere. And you could never have
separated out your interface and implementation bundles if you had to provide a
static factory that was closely coupled to implementation internals.
As you try to break the static factory habit and replace it with services, you may find
you have to change how you're thinking in other areas. For example, the apparently
inoffensive listener pattern often relies heavily on the factory pattern. Just as they
allow you to avoid static factories, OSG i services also allow you to get more from your
listener while writing less code.
Search WWH ::