Monday, June 15, 2015

factory-design-pattern-using-reflection.html

Monday, April 1, 2013

Factory Design Pattern using Reflection

Here I have given an implementation of Factory design pattern in Java using reflection.Please refer to the below link for a quick presentation about Java Refection APIs.

www.cs.washington.edu/education/courses/.../reflection.ppt

I am creating a DB factory which will create an instance of Database manager objects depends on the argument which is passed. Assume that we have an application running in 2 different environment where one environment uses Oracle as a database and another uses Solaris as a database.Upon initialization of the program we have to create a DB manager instance which should return Oracle or Solaris DB manager for the program.

Here I have used reflection to avoid modification to the Factory class if we need to support a new data base tomorrow.

I have factory class as below, DBFactory.java

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;


public class DBFactory {

    private static HashMap m_RegisteredDatabases = new HashMap();

    public static void registerProduct (String id, Class<?> dbclass)
    {
        m_RegisteredDatabases.put(id, dbclass);
    }
    
    public static DBmanager createDBmanager(String id) throws Exception, NoSuchMethodException
    {
        Class dbclass = (Class) m_RegisteredDatabases.get(id);
        Method m = dbclass.getMethod("getInstance", null);
        DBmanager mgr = (DBmanager) m.invoke(null, null);
        return mgr;
        
    }
}

here a hashmap is used tyo maintain the list of registered databases as you see and createDBManager() method uses reflection to call getInstance() method of corresponding class. This avoids modifications to DBFactory.java if a new database is introduced.

An interface is created DBmanager.java
public interface DBmanager {
    
    public void execute();
    
}

Two concrete classes OracleDBmanager.java and SolarisDBmanager.java as below


public class OracleDBmanager implements DBmanager {
    private static DBmanager instance;    
    public static DBmanager getInstance()
    {
        if ( instance == null)
        {
            synchronized (OracleDBmanager.class )
            {
                if ( instance == null)
                {
                    instance = new OracleDBmanager();
                }
            }
        }
        return instance;
    }
    
    public void execute()
    {
        System.out.println("inside OracleDBmanager execute");
    }
}

public class SolarisDBmanager implements DBmanager {
    private static DBmanager instance;    
    public static DBmanager getInstance()
    {
        if ( instance == null)
        {
            synchronized (SolarisDBmanager.class )
            {
                if ( instance == null)
                {
                    instance = new SolarisDBmanager();
                }
            }
        }
        return instance;
    }
    
    public void execute()
    {
        System.out.println("inside SolarisDBmanager execute");
    }
}

The client side code is shown as below in Reflection.java.

public class Reflection {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        DBFactory.registerProduct("env1", OracleDBmanager.class);
        DBFactory.registerProduct("env2", SolarisDBmanager.class);
        DBmanager instance;
        try {
            instance = DBFactory.createDBmanager("env1");
            instance.execute();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}

Here you see that we have registered the databases upon startup and depends on the argument to factory method, it will create Oracle or Solaris DB manager instances.

Suppose we need to support SQLserver then we need to have a SQLserverDBmanager as below.

public class SQLserverDBmanager implements DBmanager  {

    private static DBmanager instance;    
    public static DBmanager getInstance()
    {
        if ( instance == null)
        {
            synchronized (OracleDBmanager.class )
            {
                if ( instance == null)
                {
                    instance = new SQLserverDBmanager();
                }
            }
        }
        return instance;
    }
    
    public void execute()
    {
        System.out.println("inside SQLServerDBmanager execute");
    }
}

We only need to modify the client side code in Reflection.java.

public class Reflection {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        DBFactory.registerProduct("env1", OracleDBmanager.class);
        DBFactory.registerProduct("env2", SolarisDBmanager.class);
        DBFactory.registerProduct("env3", SQLserverDBmanager.class);
        DBmanager instance;
        try {
            instance = DBFactory.createDBmanager("env3");
            instance.execute();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

T

No comments:

Post a Comment