46. What is a factory pattern

A Factory method pattern is a creational pattern. The creational patterns abstract the object instantiation process by hiding how the objects are created and make the system independent of the object creation process. An Abstract factory pattern is one level of abstraction higher than a factory method pattern, which means it returns the factory classes.

Factory method pattern

Abstract factory pattern

Factory for what? Factory pattern returns one of the several product subclasses. You should use a factory pattern If you have a super class and a number of subclasses, and based on some data provided, you have to return the object of one of the subclasses. Let’s look at a sample code:


public interface Const {

public static final int SHAPE_CIRCLE = 1;

public static final int SHAPE_SQUARE = 2;

public static final int SHAPE_HEXAGON = 3;

}


public class ShapeFactory {

public abstract Shape getShape(int shapeId);

}


public class SimpleShapeFactory extends ShapeFactory

throws BadShapeException {

public Shape getShape(int shapeTypeId){

Shape shape = null;

if(shapeTypeId == Const.SHAPE_CIRCLE) {

//in future can reuse or cache objects.

shape = new Circle();

}

else if(shapeTypeId == Const.SHAPE_SQUARE) {

//in future can reuse or cache objects

shape = new Square();

}

else throw new BadShapeException

(“ShapeTypeId=+ shapeTypeId);

return shape;

}

}


Now let’s look at the calling code, which uses the factory:

ShapeFactory factory = new SimpleShapeFactory();

//returns a Shape but whether it is a Circle or a

//Square is not known to the caller.

Shape s = factory.getShape(1);

s.draw(); // circle is drawn

//returns a Shape but whether it is a Circle or a

//Square is not known to the caller.

s = factory.getShape(2);

s.draw(); //Square is drawn



An Abstract factory pattern is one level of abstraction higher than a factory method pattern, which means the abstract factory

returns the appropriate factory classes, which will later on return one of the product subclasses. Let’s look at a sample code:


public class ComplexShapeFactory extends ShapeFactory {

throws BadShapeException {

public Shape getShape(int shapeTypeId){

Shape shape = null;

if(shapeTypeId == Const.SHAPE_HEXAGON) {

shape = new Hexagon();//complex shape

}

else throw new BadShapeException

(shapeTypeId= + shapeTypeId);

return shape;

}

}


Now let’s look at the abstract factory, which returns one of the types of ShapeFactory:


public class ShapeFactoryType throws BadShapeFactoryException {

public static final int TYPE_SIMPLE = 1;

public static final int TYPE_COMPLEX = 2;

public ShapeFactory getShapeFactory(int type) {

ShapeFactory sf = null;

if(type == TYPE_SIMPLE) {

sf = new SimpleShapeFactory();

}

else if (type == TYPE_COMPLEX) {

sf = new ComplexShapeFactory();

}

else throw new BadShapeFactoryException(“No factory!!”);

}

}


Now let’s look at the calling code, which uses the factory:


ShapeFactoryType abFac = new ShapeFactoryType();

ShapeFactory factory = null;

Shape s = null;

//returns a ShapeFactory but whether it is a

//SimpleShapeFactory or a ComplexShapeFactory is not

//known to the caller.

factory = abFac.getShapeFactory(1);//returns SimpleShapeFactory

//returns a Shape but whether it is a Circle or a Pentagon is

//not known to the caller.

s = factory.getShape(2); //returns square.

s.draw(); //draws a square

//returns a ShapeFactory but whether it is a

//SimpleShapeFactory or a ComplexShapeFactory is not

//known to the caller.

factory = abFac.getShapeFactory(2);

//returns a Shape but whether it is a Circle or a Pentagon is

//not known to the caller.

s = factory.getShape(3); //returns a pentagon.

s.draw(); //draws a pentagon


Why use factory pattern or abstract factory pattern?

Factory pattern returns an instance of several (producthierarchy) subclasses (like Circle, Square etc), but the calling code is unaware of the actual implementation class. The calling code invokes the method on the interface (for example Shape) and using polymorphism the correct draw() method gets invoked [Refer Q8 in Java section for polymorphism]. So, as you can see, the factory pattern reduces the coupling or the dependencies between the calling code and called objects like Circle, Square etc. This is a very powerful and common feature in many frameworks. You do not have to create a new Circle or a new Square on each invocation as shown in the sample code, which is for the purpose of illustration and simplicity. In future, to conserve memory you can decide to cache objects or reuse objects in your factory with no changes required to your calling code. You can also load objects in your factory based on attribute(s) read from an external properties file or some other condition. Another benefit going for the factory is that unlike calling constructors directly, factory patterns have more meaningful names like getShape(…), getInstance(…) etc, which may make calling code more clear.

Can we use the singleton pattern within our factory pattern code?

Yes. Another important aspect to consider when writing your factory class is that, it does not make sense to create a new factory object for each invocation as it is shown in the sample code, which is just fine for the illustration purpose.

ShapeFactory factory = new SimpleShapeFactory();

To overcome this, you can incorporate the singleton design pattern into your factory pattern code. The singleton design pattern will create only a single instance of your SimpleShapeFactory class. Since an abstract factory pattern is unlike factory pattern, where you need to have an instance for each of the two factories (i.e. SimpleShapeFactory and ComplexShapeFactory) returned, you can still incorporate the singleton pattern as an access point and have an instance of a HashMap, store your instances of both factories. Now your calling method uses a static method to get the same instance of your factory, hence conserving memory and promoting object reuse:

ShapeFactory factory = ShapeFactory. Ge/tFactoryInstance();

factory.getShape();


No comments:

Post a Comment