Thursday, November 4, 2010

Design Patterns in Java - Abstract Factory and Factory Method

Introduction

These factory design patterns belong to group of patterns that are named "creational". These patterns helps in instantiation of classes. So with this pattern we separate creation process from object usage (If you think about if creation of new classes is kind of low level stuff like allocating memory for pointer...I now that it is not...but I just give a small analogy...whatever). So the name "factory" is derived from "factory of objects". In this way we do not use "new" keyword in object creation, but we use this pattern. With this pattern we choose which concrete class we will use at runtime and also in this way we can introduce new classes in our code without changing our base code.

This is all common sense to me (plain polymorphism in use...nothing more), and remember: Always program to interface not concrete class (don't you forget this!).

I will show same example for both patterns. In this example we need to decorate string text with some special characters. Nothing fancy...for example: from "decorate me" we will have "** decorate me **". So we just put two stars at end and beginning. All my examples are simple, because I want to concentrate at topic and at current problem.

Factory method

/**
 * Simple example of Factory Method pattern.
 * @author jan.krizan
 */
interface Decorator {

    String doDecorating(String str);
}

class StarDecorator implements Decorator {

    public String doDecorating(String str) {
        return "** " + str + " **";
    }
}

class OtherDecorator implements Decorator {

    public String doDecorating(String str) {
        return "<<|-- " + str + " --|>>";
    }
}

public class Factory {

    public static final int STAR_DECORATOR = 1;
    public static final int OTHER_DECORATOR = 2;

    public static Decorator createSpecificDecorator(int i) {
        if (i == STAR_DECORATOR) {
            return new StarDecorator();
        } else if (i == OTHER_DECORATOR) {
            return new OtherDecorator();
        } else {
            return null;
        }
    }

    public static void main(String[] args) {

        String nonDecoratet = "Please decorate me!";

        Decorator decorator = createSpecificDecorator(STAR_DECORATOR);

        System.out.println(decorator.doDecorating(nonDecoratet));
    }
}
Output of this example is: "** Please decorate me! **". No kidding...really! :) Ok, never mind that, let's comment it!:
(5 - 8) We first create interface.
(10 - 15 and (17 - 22) Then we implement that interface.
As you can see all straight forward for now.
(29 - 37) This represent factory that will choose (base on input parameter) which
class to instantiate.
Then we test the stuff in main.

Abstract factory

Abstract factory is (as you can figure out from its name) in higher level at higher level of abstraction. In abstract factory event the factory is abstract (interface or abstract class) and we choose factory at runtime (not the "working" class). The factory will "know" which class it need to instantiate in order to fulfill job in hand.

/**
 *
 * Simple example of Abstract Factory pattern.
 * @author jan.krizan
 */
interface DecoratorFactory {

    Decorator createDecorator();
}

class StarDecoratorFactory implements DecoratorFactory {

    public Decorator createDecorator() {
        return new StarDecorator();
    }
}

class OtherDecoratorFactory implements DecoratorFactory {

    public Decorator createDecorator() {
        return new OtherDecorator();
    }
}

interface Decorator {

    String doDecorating(String str);
}

class StarDecorator implements Decorator {

    public String doDecorating(String str) {
        return "** " + str + " **";
    }
}

class OtherDecorator implements Decorator {

    public String doDecorating(String str) {
        return "<<|-- " + str + " --|>>";
    }
}

public class Factory {

    public static final int STAR_DECORATOR = 1;
    public static final int OTHER_DECORATOR = 2;

    public static DecoratorFactory createSpecificDecorator(int i) {
        if (i == STAR_DECORATOR) {
            return new StarDecoratorFactory();
        } else if (i == OTHER_DECORATOR) {
            return new OtherDecoratorFactory();
        } else {
            return null;
        }
    }

    public static void main(String[] args) {

        String nonDecoratet = "Please decorate me!";

        DecoratorFactory decoratorFac = createSpecificDecorator(OTHER_DECORATOR);

        Decorator decorator = decoratorFac.createDecorator();

        System.out.println(decorator.doDecorating(nonDecoratet));
    }
}

Here we see that code is almost same as for Factory Method. There are just small but important differences:
(11 - 16 and 18 - 23) Here we create another layer, this seem like waste of code, but this can be beneficiary if for example we have more than one method to implement and we don't want all method to implement (just subset). In this way we in our concrete classes implement only those method we need for our work and ignore other. We can extends one interfaces to accomplish this. If this sound a little bit confusing for you, don't worry and search some good example of Abstract Factory and you will see what I talking about. For example here.

Creating class instances is similar and also testing is similar, we just have another step and that is to obtain Decorator class through createDecorator method.

Using Abstract Factory pattern for simple example like this is stupid and overkill, but I want to show differences between the two patterns.

You can download code for this two examples from here.

No comments:

Post a Comment