Factory Design Pattern

Factory design pattern is one of the creational design pattern for creating objects with respect to Object Oriented systems.What is the most usual method of creating object,most people think that using new keyword.But creating object with new keyword makes components tightly coupled,if we need to change object creation process then we need to change it in all places in our programme. So in order to make components loosely coupled Factory pattern is one solution.Loose coupling is achieved in Factory pattern by implenting at interfaces and not at concrete classes.

The intent of factory pattern is:

1.Creates the object without exposing object creation logic to client
2.refers to newly created object through common interface(through factory)

Lets take look at example where we need various DB connectors like MsSQLConnector,OracleConnector and SQLServerConnector,we can use factory design pattern.

1.Connector Type enum:

package com.dp.factory;

public enum ConnectorType {
    MsSQlConnector, OracleConnector, SQLserverConnector
}


2.Connector interface:
package com.dp.factory;

public interface Connector {
    
    public void connect();

}


3.Concrete MsSQLConnector class:
package com.dp.factory;

public class MsSQLConnector implements Connector {
    
    public MsSQLConnector() {
        connect();
    }

    @Override
    public void connect() {
        System.out.println("Connecting to MsSQLDatabase.!!!!!!!!");

    }

}


3.Concrete OracleConnector class:
package com.dp.factory;

public class OracleConector implements Connector {
    
    public OracleConector() {
        connect();
    }

    @Override
    public void connect() {
        System.out.println("Connecting to oracle database.!!!!!!!!!");

    }

}


3.Concrete SQLServerConnector class:
package com.dp.factory;

public class SQLServerConnector implements Connector {
    
    public SQLServerConnector() {
        connect();
    }

    @Override
    public void connect() {
        System.out.println("Connecting to SQLConnector database.!!");
        
    }

}


4.Factory class to get connector type:
package com.dp.factory;

public class DBConnectorFactory {
    
    public static Connector getDBConnector(ConnectorType type){
        Connector connector = null;
        switch(type){
        case MsSQlConnector :
            connector = new MsSQLConnector();
            break;
        case OracleConnector :
            connector = new OracleConector();
            break;
        case SQLserverConnector : 
            connector = new SQLServerConnector();
            break;
        }
        return connector;
    }

}


5.Client:
package com.dp.factory;

public class Client {
    
    public static void main(String[] args) {
        Connector connector = null;
        connector = DBConnectorFactory.getDBConnector(ConnectorType.MsSQlConnector);
        System.out.println(connector.getClass().getName());
        connector  =DBConnectorFactory.getDBConnector(ConnectorType.OracleConnector);
        System.out.println(connector.getClass().getName());
        connector = DBConnectorFactory.getDBConnector(ConnectorType.SQLserverConnector);
        System.out.println(connector.getClass().getName());
    }

}



This is the simple and intutive implmentaion for factory pattern.What if we need to add one more concrete DBConnector as DB2Connector?...we need to modify factory class to add one more switch case for DB2Connector type of objects.But this is against Open Close principle of Object oriented programming.

Need to change Factory and client and Concrete classes as well:
So the code looks like:

package com.dp.factory;

public enum ConnectorType {
    MsSQlConnector, OracleConnector, SQLserverConnector
}


package com.dp.factory;

public interface Connector {
    
    public void connect();

}


package com.dp.factory;

public class MsSQLConnector implements Connector {
    
    
    static{
        DBConnectorFactory.getInstacne().addConnector(ConnectorType.MsSQlConnector,  MsSQLConnector.class);
    }
    
    public MsSQLConnector() {
        connect();
    }

    @Override
    public void connect() {
        System.out.println("Connecting to MsSQLDatabase.!!!!!!!!");

    }

}


package com.dp.factory;

public class OracleConector implements Connector {
    
    static{
        DBConnectorFactory.getInstacne().addConnector(ConnectorType.OracleConnector,  MsSQLConnector.class);
    }
    
    public OracleConector() {
        connect();
    }

    @Override
    public void connect() {
        System.out.println("Connecting to oracle databse.!!!!!!!!!");

    }

}




package com.dp.factory;

public class SQLServerConnector implements Connector {
    
    static{
        DBConnectorFactory.getInstacne().addConnector(ConnectorType.SQLserverConnector,  MsSQLConnector.class);
    }
    
    public SQLServerConnector() {
        connect();
    }

    @Override
    public void connect() {
        System.out.println("Connecting to SQLConnector database.!!");
        
    }

}


package com.dp.factory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class DBConnectorFactory {
    static DBConnectorFactory factory = null;
    private DBConnectorFactory(){
        
    }
    private Map registeredConnectors = new HashMap<>();
    
    public void addConnector(ConnectorType connectorType,Class connectortypeClass){
        registeredConnectors.put(connectorType, connectortypeClass);
    }
    
    public Connector getDBConnectorFromMap(ConnectorType type) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
        Class connectorClass = (Class)registeredConnectors.get(type);
        Constructor[] connectorConstructor = connectorClass.getConstructors();
        return (Connector)connectorConstructor[0].newInstance(new Object[] { });
    }
    
    public static DBConnectorFactory getInstacne(){
        
        if(factory == null){
            factory = new DBConnectorFactory();
            return factory;
        }
        else{
            return factory;
        }
    }

}


package com.dp.factory;

import java.lang.reflect.InvocationTargetException;

public class Client {
    
    
    static{
        try
        {
            Class.forName("com.dp.factory.MsSQLConnector");
            Class.forName("com.dp.factory.OracleConector");
            Class.forName("com.dp.factory.SQLServerConnector");
        }
        catch (ClassNotFoundException any)
        {
            any.printStackTrace();
        }
    }
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        
        
        Connector connector = DBConnectorFactory.getInstacne().getDBConnectorFromMap(ConnectorType.MsSQlConnector);
    }

}



Comments