Saturday, September 07, 2013

Abstract Factory

The Abstract Factory pattern provides an interface that delegates creation calls to one or more concrete classes in order to deliver specific objects. Following is the definition provided for the pattern in the GoF book on Design Patterns:

Abstract Factory provides an interface for creating families of related or dependent objects without specifying their concrete classes.

Abstract factory relies on object composition – i.e. object creation is implemented in methods exposed in the factory methods. The intent of the pattern is to create families of related objects without having to depend on their concrete classes.

First we define the interface and implementation of the object that we want to create:

public interface Car {

    

    public void setDescription(String description);


 

    public void refuel();

}


 

public class EVCar implements Car {


 

    @Override

    public void setDescription(String description) {

        // set description

    }


 

    @Override

    public void refuel() {

        // electric charging

    }


 

}


 

public class HybridCar implements Car {


 

    @Override

    public void setDescription(String description) {

        // set description

    }


 

    @Override

    public void refuel() {

        // refuel with gas

    }


 

}


 

Now we define the factories, starting with an abstract factory:

public interface AbstractCarFactory {

    public Car createCar();

}


 

Next the actual implementations of the factory:

public class EVCarFactory implements AbstractCarFactory {


 

    @Override

    public Car createCar() {

        EVCar evCar = new EVCar();

        return evCar;

    }

}


 

public class HybridCarFactory implements AbstractCarFactory {


 

    @Override

    public Car createCar() {

        HybridCar hybridCar = new HybridCar();

        return hybridCar;

    }


 

}


 

Now let's test drive this factory:

public class AbstractFactoryTest {

    AbstractCarFactory abstractCarFactory = null;

    

    @Test

    public void evCarFactoryTest() {

        abstractCarFactory = new EVCarFactory();

        abstractCarFactory.createCar();

    }

    

    @Test

    public void hybridCarFactoryTest() {

        abstractCarFactory = new HybridCarFactory();

        abstractCarFactory.createCar();

    }

}


 

While the pattern hides the implementation details from the client, there is always a chance that the underlying system will need to change – for example new attributes might be added to Car or AbstractCarFactory, which would mean a change to the interface that the client was relying on, thus breaking the API.

No comments: