When you need to query the services, you often end up with code that loops over all available instances. For example, when you want to create a layer for a model, you would request all layer factories from the services and loop over them until you encounter a layer factory that accepts the model.
To prevent such boilerplate code, the Lucy API comes with composite implementations for all interfaces, available as services. To learn more about composite patterns, see the web page The composite pattern.
The available services documentation contains an overview of the available composite implementations. |
For this example, we use the TLcyCompositeGXYLayerFactory
,
which is a composite implementation of ILcdGXYLayerFactory
. As you can see in the Javadoc of TLcyCompositeGXYLayerFactory
, two constructors are available:
the default constructor and a constructor with an ILcyLucyEnv
parameter.
The default constructor creates a regular composite implementation of ILcdGXYLayerFactory
,
as explained in The composite pattern.
On the other hand, the constructor with the ILcyLucyEnv
parameter works on the registered service
objects of the Lucy back-end. You can add or remove an ILcdGXYLayerFactory
instance to or from this
composite instance through the services:
ILcdGXYLayerFactory
directly as service object on the back-end
ILcdGXYLayerFactory firstLayerFactory;
ILcyLucyEnv aLucyEnv;
aLucyEnv.addService(firstLayerFactory);
or through a new instance of TLcyCompositeGXYLayerFactory
:
ILcdGXYLayerFactory
as service object trough a composite implementation
ILcdGXYLayerFactory secondLayerFactory;
ILcyLucyEnv aLucyEnv;
new TLcyCompositeGXYLayerFactory(aLucyEnv).addGXYLayerFactory(secondLayerFactory);
Because the TLcyCompositeGXYLayerFactory
works directly on the Lucy services, it has no internal
state and you can create a new instance whenever you need one, for example:
ILcdGXYLayerFactory thirdLayerFactory, fourthLayerFactory;
new TLcyCompositeGXYLayerFactory(aLucyEnv).addGXYLayerFactory(thirdLayerFactory);
new TLcyCompositeGXYLayerFactory(aLucyEnv).addGXYLayerFactory(fourthLayerFactory);//we may create a new TLcyCompositeGXYLayerFactory, or re-use the existing one
The code snippets above will result in four ILcdGXYLayerFactory
instances registered
as services with the Lucy back-end:
ILcyLucyEnv aLucyEnv;
aLucyEnv.getServices(ILcdGXYLayerFactory.class).size();//this will return 4
new TLcyCompositeGXYLayerFactory(aLucyEnv).getGXYLayerFactoryCount();//this will also return 4
Warning: although the composite implementations and the services behave very similarly, there are two possible pitfalls when you are using them both:
-
If you add an object A through the Lucy services —
ILcyLucyEnv.addService(A)
— , you can only remove it through the services, and not through a composite implementation —ILcyLucyEnv.removeService(A)
).This restriction also applies to the composite implementations. Objects you add to the composite implementation can only be removed through a back-end-based composite implementation. and not directly through the services.
This also applies to the
ALcyFormat
instances. When using aTLcyFormatTool
to plug in anALcyFormat
, you should also use theTLcyFormatTool
to unplug theALcyFormat
. -
Adding an object through the Lucy services —
ILcyLucyEnv.addService(Object)
— registers the object for every interface or class it implements or extends, while in the composite implementation it is only registered for the specified class. Let us go back to the example of theTLcyCompositeGXYLayerFactory
. Suppose we have aILcdGXYLayerFactory
that also implementsILcdGXYLayerDecoder
andILcdGXYLayerEncoder
. Registering it directly with the services leads to:Program: Registering an object which implements multiple interfaces directly to the servicesILcyLucyEnv aLucyEnv; ILcdGXYLayerFactory layerFactory;//suppose it also implements ILcdGXYLayerDecoder, ILcdGXYLayerEncoder aLucyEnv.addService(layerFactory); aLucyEnv.getServices(ILcdGXYLayerFactory.class);//returns a list containing layerFactory aLucyEnv.getServices(ILcdGXYLayerDecoder.class);//returns a list containing layerFactory aLucyEnv.getServices(ILcdGXYLayerEncoder.class);//returns a list containing layerFactory
Performing the same operation on the
TLcyCompositeGXYLayerFactory
only registers theILcdGXYLayerFactory
as layer factory, and not asILcdGXYLayerDecoder
orILcdGXYLayerEncoder
:Program: Registering an object which implements multiple interfaces through a composite implementationILcyLucyEnv aLucyEnv; ILcdGXYLayerFactory layerFactory;//suppose it also implements ILcdGXYLayerDecoder, ILcdGXYLayerEncoder TLcyCompositeGXYLayerFactory composite = new TLcyCompositeGXYLayerFactory(aLucyEnv); composite.addGXYLayerFactory(layerFactory); aLucyEnv.getServices(ILcdGXYLayerFactory.class);//returns a list containing layerFactory aLucyEnv.getServices(ILcdGXYLayerDecoder.class);//returns a list which does NOT contain layerFactory aLucyEnv.getServices(ILcdGXYLayerEncoder.class);//returns a list which does NOT contain layerFactory