|
|
[i]Paste from c2 wiki[/i] Problem
How can you parameterise the behaviour of a Java program based on external data?
Context
You often need to modify the behaviour of a program based on external data, such as a command-line parameter. If you hard-code a finite set of acceptable parameter values into a program you will have to modify the program whenever you need to add new parameters. The deployment of new versions will become more complex as the number of installed programs increases. If programs need to interpret parameters in order to interoperate (for example, if the parameters are read from network messages), you must ensure that all users upgrade before they can communicate, which becomes very difficult with large user bases.
Solution
Take advantage of Java's built-in facilities for dynamic loading and linking of code. Dynamically load and instantiate classes of behaviour corresponding to external parameters.
- Define an interface through which to access the parameterised behaviour
- Define a naming scheme that maps user-specified parameters to the name of a Java class.
- Define classes that implement the interface for various parameters, and follow the naming scheme so that they can be found by the parameter-to-name mapping.
- At run time, given a parameter value, map it to the name of the Java class that performs the required behaviour.
- Dynamically load that class using the Class.forName method.
Instantiate an object of the class using the Class.newInstance method or via a Constructor of the class.
- Cast the object to the interface you have defined and pass it to the objects that need to use the parameterised behaviour.
Resulting Context
The behaviour of the Java program can be parameterised by simple values, such as short string names, or more complex values by creating a more elaborate scheme for mapping from parameters to classes.
A large, perhaps unbounded, range of behaviours can be described in this way.
Parameterisation does not impact runtime performance beyond the price of dynamically dispatched method calls.
New parameter values can be introduced without having to change the code that uses those values.
It is difficult to list all possible values, so that they can be displayed to the user, for example.
All ParameterClasses must be modified if the interface between the program and the ParameterClasses is changed.
Initialisation time is increased if the Reflection API must be used to query ParameterClasses for an appropriate Constructor.
If some ParameterClasses need to extend the plug-in interface, then you should define thoses extended interfaces as InterfacesIndependentOfImplementation.
Related Patterns
ParameterClasses is a JavaIdiom for mapping from a user-visible parameter to a class that implements the behaviour specified by that parameter. How that class is subsequently used is beyond the scope of this pattern. The class may be used as a StrategyPattern or a BridgePattern, or in some other manner.
This pattern uses the FactoryPattern in three distinct ways: [i]ClassLoaders[/i] or the [i]java.lang.Class.forName[/i] method are used as factories of [i]java.lang.Class[/i] objects that represent dynamically loaded classes. In this case, the class loaders are examples of the AbstractFactoryPattern. Instances of [i]java.lang.Class[/i] class are used as factories for concrete plugin implementations (the AbstractFactoryPattern). The use of the ParameterClasses idiom is often hidden within a factory object in order to provide clients with a convenient API, but this does not have to be an abstract factory.
You may need to EncapsulateMultiStageConstruction of parameter objects, or TestWhetherInConstructionPhase when initialising them.
You can use InterfaceFactories to encapsulate the mapping from parameter values to class names.
Known Uses
The JavaIo package uses this idiom to name character encoding schemes that convert between Unicode characters and raw bytes.
The Java Media Framework (JMF) uses this idiom to specify codecs by media type and name sources of media.
The Java AWT uses this idiom to specify the GUI JavaAwtToolkit used by the JVM.
The Regent distributed programming environment uses this idiom to specify transport protocols for intercomponent bindngs.
NatPryce has written a compiler in which the back-end is implemented as ParameterClasses. Thus different code-generators can be loaded based on command-line options.
JDBC is almost like this, except there isn't a standard place to put JDBC drivers so they will automatically be loaded.
Applets work this way (the parameter is the URL.)
More Information
There is a very good introduction to Java class loaders and dynamic linking on the Java World web site at here |
|