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.

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.

ClassLoaders or the java.lang.Class.forName method are used as factories of java.lang.Class objects that represent dynamically loaded classes. In this case, the class loaders are examples of the AbstractFactoryPattern.

Instances of java.lang.Class 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.

Even after reading all this, I'm not sure I understand the purpose of ParameterClasses. I guess a small sample of code could, like a drawing, save much time in explanations

Ok... let's use crypto as an example. We want to encrypt and decrypt data. There are a number of cryptographic algorithms (aka "ciphers") we can choose between, such as DES, Triple-DES or IDEA. We don't want to limit ourselves to a single cipher because, for example, our app will be decrypting encrypted mail where the sender will have chosen the cipher, and named the cipher in the mail headers. We also don't want to limit our app to a fixed set of ciphers, because new ciphers will be introduced as older ciphers are found to be insecure. We also don't want to limit our app to a single implementation for any cipher, because our users will want to choose a cipher implementation that they trust, and change implementations that they decide are untrustworthy. So, ciphers must be identified by parameters provided from external sources (mail messages),
and these parameters must be mapped to implementations of the cipher (Java classes) that are dynamically loaded into our application.

Ciphers are implemented as concrete classes that implement the Cipher interface. These are the ParameterClasses. They are dynamically loaded and instantiated when the application asks for a Cipher by name.

Ciphers are loaded by the newCipher method of the
CipherFactory class. This method first maps the name of a cipher to a class, and then instantiates the class to create a new Cipher.

The CipherFactory translates a parameter into a class by loading a class named after the cipher with "Cipher" prepended, in a subpackage of "com.examplecorp.cipher" that has the same name as the cipher, but lowercase.
E.g. the ParameterClass for the DES protocol would be com.examplecorp.cipher.des.CipherDES.

In practice, you would want to search for a class in a number of packages so that new packages of ciphers could be added to the system (e.g. search uk.mil.cipher and com.examplecorp.cipher), use a properties file to control how to find packages so that the class loading algorithm can be configured without recompiling the application, allow users to specify JAR files or URLs to search for classes, and so on.

This was in the Resulting Context, but I modified it up there. This is the rationale for that edit:

"Initialisation time is increased because objects must be instantiated and invoked via the Java Reflection API."

Reflection API is not required to invoke the methods of instances of ParameterClasses, due to step 1 of the solution. The parameter class itself must be dynamically loaded, and the Reflection API might be needed to find an appropriate constructor of the loaded class. Once an instance is created it is cast to a a well-known interface and invoked through that interface.
--NatPryce

Im currently writing (in C++) a application that allows a sort of "visual programming" by connecting blocks together. The blocks are instances of classes written by the user. If only C++ had Java's ability to load classes on the fly and inspect the signature of their m ethods programmatically! I even considered doing it in Java instead of C++. But we want to use the app for number crunching, and sorry, Java just isn't fast enough for that.

So I did something in C++. It relies on the user writing a small piece of registration code for every class that is to be used. The solution relies rather
heavily on templates to allow two functions to be connected if their types match, even if this type wasn't yet defined at the time the code that does the connecting was written.

I think it is a rather workable solution. Best of all: it is 100% Pure C++.

This multi-language benchmark uses floating-point arithmetic to compute the "is the point inside the polygon" test. Here are the results (those with John Watton's paper can compare to the paper's results based on the performance of the first case).

In my experience one can develop reliable code must faster in Java than in C++. I would suggest writing your application in Java and then using AlternateHardAndSoftLayers to integrate CPU intensive algorithms written C if performance is actually too slow in practice.

You can use ParameterClasses to select between native and Java implementations of your algorithms, so that your program loads the native version on platforms for which native code exists and the pure Java version on other platforms. I have used ParameterClasses for this very purpose in a network protocol framework, so that programs could use native interfaces to the TCP and UDP protocols if they existed or fall back on slower implementations that used the java.net package if native versions were not available.

This idiom has turned out to be an extremely good fit with ExtensibleMarkupLanguage. For example, the configuration of Tomcat is done with XML files, and many of the parameters specify classes that implement an interface and are used for various services. For example, this snippet:

The former implements a simple file-based authentication scheme, the latter implements authentication via a database. It is trivial to create your own authentication Realm by implementing RequestInterceptor (actually most likely extending the no-op BaseInterceptor? adaptor) and writing a different authenticate() method.

Notice the attributes -- they correspond to bean methods that the framework can call, and your class can be configured competely from the config file.

In hindsight I think the name "ParameterClasses" is pretty poor. PluginClass? or NamedPluginClass? would be better, for example. I need a rename page mechanism that renames all links to a page.
--NatPryce

This looks like a variation of FactoryPattern to me:
You're creating instances of a set of classes, without tying yourself to the specific implementations of those classes.
I might call it DynamicClassFactory? to emphasize its runtime behavior of dynamically loading classes to create instances.
-- JeffGrigg

ClassLoaders or the java.lang.Class.forName method are used as factories of java.lang.Class objects that represent dynamically loaded classes. In this case, the class loaders are examples of the AbstractFactoryPattern.

Instances of java.lang.Class 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.

This idiom isn't limited to interpreting command line parameters, is it? No.

So what does it do?

Well, it...

Accepts a text string input that describes the kind of processing that needs to be done.

Using <some rules>, it finds an appropriate class and creates an instance of that class. The instance will do the appropriate processing.

The class of the instance being created is not known the the caller at design/compile time. (All that is known is that the instance will implement certain acceptable interface(s).)

Looks like a factory to me.
Now it is significantly different from the "factory" patterns found in the GangOfFourDesignPatterns book, and close relatives:
No one is passing you an instance that will "do the appropriate creation" for you.

Do we agree that it falls into the CreationalPatterns category?
...that it is a strategy for creating objects?

Yes, FactoryPattern/AbstractFactoryPattern and StrategyPattern are used to implement this pattern, but that doesn't imply that this pattern >is< one of its implementation details.
You should use a name that is illustrative of the overall function.
The new name may or may not have the words "factory" or "strategy" in it; try to find a name that works for people.
-- JeffGrigg

I think you are concentrating too much on the implementation details of this pattern and not looking at the problem and context. Yes, the static structure solution is similar to that of strategy, factory, bridge and a load of other patterns. Let's face it, any design pattern involves only a few classes and there are only a finite number of ways those classes can be related, so all patterns look kind of similar if you ignore the problem and context.

If we can parameterize part of the class name, why not simply parameterize the entire class name? Actually this is what JDBC does. What the class name parameterization buys you is the controlled naming convention, probably more for the control of the package structure, but again this can be easily achieved by configure the allowable class names. So to me this is more of a "DynamicClassLoadingPattern?" derived from "AbstractFactoryPattern" instead of a somewhat more independent pattern.
--HChen

You can do, if that makes sense for your application. But in doing so you lose a level of indirection, make the interface more complex to users and make it harder to parse data from programs written in other languages. Using the Cipher example, if I use a class name to identify ciphers I am (a) identifying cipher implementations, which stops me being able to choose a different implementation of the same cipher (b) force users to use class names for ciphers instead of the algorithm names that they are already used to (b) am unable to process encrypted mail messages because they use algorithm names to identify ciphers, not Java classes.

So the intent of the ParameterClasses pattern is to map from a user friendly parameter to the behaviour that is implied by that parameter and that is implemented by a Java class. Using a full class name as a parameter is a degenerate case of this pattern.