IoC Design Pattern

Posted 1095 days ago

I had read something a while ago about a design pattern called Inversion of Control (IoC), which came back to me this morning as I was working. I looked it up on Google and found a decent overview of the pattern, and wanted to share it: IoC Article

The basic jist of IoC is that if your class needs an object that is outside of its primary responsibilities, it should not instantiate it itself, but rather should accept that object either in a constructor or with a setter method. This writeup uses a database object manager for it's example, however a more common example is logging. I'd be willing to bet that at the top of most Java Code with logging, you'd see a line that looks like this:

private final static Logger LOG = Logger.getLogger( myclass.class );

And then the rest of the methods in that class use the LOG instance. IoC says that it is NOT your class' responsibility to instantiate a logger, and therefor should be passed one instead.

Some benefits to doing this:

  1. It ties in well with Test-First programming, as it helps to minimize the amount of setup needed in your testcases. In the case of logging, it means that you can pass in a "dummy" Log implementation rather than configuring a Log4J runtime.
  2. It allows us to log based on "use-cases" rather than at a functional level. Take for instance the core/Reports framework. Every class in core/Reports right now has it's own logger, but in general, I only use 2 or 3 of the classes in the package (t he classes which expose the high-level functionality of the framework). If I implemented IoC with respect to Logging in core/Reports, I'd probably only have 2 distinct Log instances in the entire package, making it a) easy to configure logging for core/re ports and b) easy to identify flow-of-control in the logging output.
  3. It minimizes the amount of work we need to do when we all of a sudden decide we want to, say, drop in commons-logging rather than use Log4J directly :).

IoC happens to be very easy to re-factor in, here's an example of how that would be done without breaking compatibility:

Existing Class:

public Class Foo { private final static Logger LOG = Logger.getLogger( Foo.class ); public Foo() { // Initialize the class here. } ... }

Refactored class:

public Class Foo {
    private Logger LOG = null;

    public Foo() {
	// Default constructor creates a logger so 
	// as to not break any existing code.
        this( Logger.getLogger( Foo.class ) );    
    }

    /**
     * New usages of Foo should use this class 
     * instead, passing in a Logger instance.
     */
    public Foo( Logger log ) {        
        // Initialize the class here.
        this.LOG = log;
    }

    public void setLogger( Logger log ) {
        this.LOG = log;
    }
}

You should really take the time at this point to find usages of the "old" constructor, update them to usages of the new constructor, and remove the old constructor. This may not be very easy to accomplish, especially when you're refactoring libraries.. . The refactoring shown above guarantees that no current usages of your code will break. New code, however, should implement IoC and NOT give users the option of using a Default logger, as follows:

New Class:

public Class NewFoo {
    private Logger LOG = null;

    // Explicitly remove the ability of constructing 
    // this class w/o a logger. This prevents outside 
    // instantiations, and subclasses of this class 
    // from doing this.
    private NewFoo() {
    }

    public NewFoo( Logger log ) {
        this.LOG = log;
    }
}
Anonymous Abstract Factory pattern revisited

Posted 1378 days ago

A while ago I had posted an article about the Anonymous Abstract Factory Pattern - an adaptation of the Abstract Factory Pattern that takes advantage of anonymous class loading in Java. Well I've finally got around to pulling the framework for that pattern out of the jETIA source tree, so I CPL'd it and am making it available here: AnonymousAbstractFactory-1.0.0.tar.bz2.

Please let me know if you're interested in working on the project. I'd love to get a couple developers working on it, adding features such as support for factory constructors, configurable factories, and a few other features. If I get a couple people who are interested, I'll set up an SVN repository for the project and we'll start making plans. Sorry for the minimal documentation, I'll work on that as well.

Abstract Anonymous Factory Pattern

Posted 1576 days ago

A factory is an object that creates instances or related types of objects. An abstract factory provides the interface that factory objects implement, as well as a method return a concrete factory implementation. For example, jETIA contains an Abstract DAO Factory that defines abstract methods to get different types of data access objects, and a static method to obtain a concrete instance of a DAO Factory.

In the abstract factory pattern as described in "Design Patterns", the Abstract Factory's static method to obtain a concrete factory instance would take a parameter identifying the type of concrete factory to return, and instantiate the appropriate sub-class of itself to satisfy the request. This hard coded knowledge of the available types of concrete factories makes it difficult to supply new types of factories later.

The Abstract Anonymous Factory is an adaptation of the abstract factory pattern that takes advantage of the anonymous class loading abilities of the Java runtime environment. Instead of explicitly telling the Abstract Factory about each type of Factory, the Abstract Anonymous Factory reads information about the types of concrete factories from a configuration file. The anonymous abstract factory then asks the runtime environment to find the class by name, and instantiate it.

Using this method, to add support for a new type of factory, the developer must implement the objects that are created by the concrete factory, create a new concrete subclass of the abstract anonymous factory, and modify a configuration file that is read dynamically at runtime. There is no need to recompile any of the code to deploy a new factory.

To help illustrate this concept, consider the sequence diagram shown the figure below. It depicts the sequence of events that occur when an application needs to use a Widget. In order to support a wide variety of widgets, an abstract anonymous widget factory is used. As you can see, the client obtains a concrete widget factory from the abstract anonymous widget factory. The configuration file is read to determine what types of widget factories are available, and in this instance, since no particular type is specified, the name of the default widget factory to use.

This is why the factory is referred to as "anonymous." Neither the client application nor the abstract factory has any advanced knowledge of the type of factory to instantiate. Since the concrete widget factory implements a known interface, it can be instantiated as a generic Object instance, and then cast to the appropriate interface type.

About

My name is Tim Fanelli, I am a software engineer in Northern NY. I spend most of my time working, and when I can, I try to post interesting things here.

Cigar Dossiers