ConstructorObject

Last edit July 24, 2012
This is a JavaIdiom rather than a proper pattern, as it uses dynamic loading. It is closely related to the AbstractFactoryPattern; in fact it's a special case of it.

Originally by TomAnderson, in violation of BuschmannsLaw and the RuleOfThree. Using CanonicalForm.

Name

Constructor Object.

(no aliases known)

Context

You have dynamically loaded a class ("the implementing class") which conforms to a statically known interface ("the main interface"). You need to be able to create instances of the implementing class; this calls for an abstract factory.

Problem

How do you create the abstract factory which matches the implementing class?

Forces

  • You have no static knowledge of the possible implementing classes, so you can't use a map or a switch: you have to dynamically load the factory class
  • All the implementing classes have the same constructor (a prerequisite for using a factory)
  • You can't invoke class methods without evil reflection (so this doesn't apply to Smalltalk)
  • You can dynamically load classes based on their name (so this doesn't apply to C++)

Solution

Define an inner 'constructor' abstract class in the main polymorphic interface, which defines methods for creating instances of the main interface (as it were). In each implementing class, define a static inner class with a standard name which extends the constructor class and has a no-args constructor. The constructor objects thus serve as lightweight factories which can be obtained in a simple manner.

Example

/* Consider a drawing package, where we have Drawings and Tools which can be applied to them. We want to be able to load Tools dynamically.
  • /

 public class Drawing
 {
 	// details not important here
 }

public interface Tool { public String getName() ; public void apply( int x, int y ) ; public static abstract class Constructor { public static final String NAME = "Constructor" ; public Tool create( Drawing d ) ; } }

public class SpraycanTool implements Tool { private Drawing d ; public SpraycanTool( Drawing d ) { this.d = d ; } public String getName() { return "Spraycan" ; } public void apply( int x, int y ) { // do spraying here } public static class Constructor extendsTool.Constructor { // no-args constructor! public Tool create( Drawing d ) { return new SpraycanTool( d ) ; } } }

// client code

public Tool createTool( String clName, Drawing d ) { /* // minor gripe; what i want to do is: Class cl = Class.forName( clName ) ; Class ccl = cl.getClass( Tool.Constructor.NAME ) ; // but there is no such method (in 1.3, at least) */ String cclName = clName + '$' + Tool.Constructor.NAME ; Class ccl = Class.forName( cclName ) ; Tool.Constructor ctor = (Tool.Constructor)ccl.newInstance() ; Tool t = ctor.create( d ) ; return t ; }

Resulting Context

  • The factory is created by several leaps of faith (there is a class with this name, that class has a no-args constructor, that class implements the right interface, that class does the right thing)
  • New instances are created by a polymorphic but non-reflective call
  • Construction is type-safe
  • Construction is quite fast (if Constructor was an abstract base class and not an interface, it might even be a dozen cycles faster)
  • There may be many instances of the factory

Tool.Constructor could have some convenience methods as follow:

 public static Tool createConstructor( String clName )
 {
 	String cclName = clName + '$' + Tool.Constructor.NAME ;
 	Class ccl = Class.forName( cclName ) ;
 	Tool.Constructor ctor = (Tool.Constructor)ccl.newInstance() ;
 	return ctor ;
 }

public static Tool createTool( String clName, Drawing d ) { Tool.Constructor ctor = createConstructor( clName ) ; Tool t = ctor.create( d ) ; return t ; }

Rationale

The AbstractFactoryPattern is the most elegant way to handle object creation in this situation; this idiom is just a simple way of getting hold of a factory.

What i mean is, "it just seems obviously right to me", which is either a very good or a very bad reason. Hmm.

Known Uses

  • I (TomAnderson) am only aware of one use of this pattern, and that's in a drawing tool that i am writing. I know, RuleOfThree, but if this idiom isn't any good, we can erase it.

Related patterns

  • This is obviously very similar to the AbstractFactoryPattern
  • Some alternatives.
    • Define an init method in the main interface which takes the parameters which would go in Constructor.create, and then have a convention that implementing classes provide a no-args constructor; instances can then be created with newInstance and initialised with init. The problem with this is that it allows uninitialised instances to exist; this can be addressed using the EssencePattern.
    • Define the standard constructor in each implementing class and just call it reflectively. The problem with this is that it has less type safety, and reflection may be slow.