Friday, June 17, 2016

Design Patterns - Factory Pattern (with Reflection API)

Factory design patterns are probably the most used design pattens in almost any kind of framework. Its part of the creational pattern as it provides a structured ways to generate objects.

To understand factory pattern, lets take an example where we develop code to print the different country codes. All the countries implement the interface called Country. The interface is as follows -

Country.java


package factory;

public interface Country {

    public void printCountryCode();
}

We consider three countries for this example - India, Germnay and Japan. Each country has a class of its own which implents the Country interface and its method printCountryCode(). The classes are given below.

India.java


package country;

import factory.Country;

public class India implements Country {

    @Override
    public void printCountryCode() {
        System.out.println("+91");
    }

}

Germany.java


package country;

import factory.Country;

public class Germany implements Country {

    @Override
    public void printCountryCode() {
        System.out.println("+49");
    }

}

Japan.java


package country;

import factory.Country;

public class Japan implements Country {

    @Override
    public void printCountryCode() {
        System.out.println("+81");
    }

}

Each class has its own version of the method printCountryCode().

Now we create a Factory class which essentially generates these classes at runtime, depending upon when its needed, and executes the printCountryCode() method. In our example, we print the country code for all the countries.


package factory;

import country.Germany;
import country.India;
import country.Japan;

public class CountryFactory {

    public static void main(String[] args) {
        Country india = getCountry("India");
        india.printCountryCode();    //Prints +91

        Country germany = getCountry("Germany");
        germany.printCountryCode();     //Prints +49
 
        Country japan = getCountry("Japan");
        japan.printCountryCode();    //Prints +81
    }

    public static Country getCountry(String name) {
        if (name.equals("India")) {
            return new India();
        } else if (name.equals("Germany")) {
            return new Germany();
        } else if (name.equals("Japan")) {
            return new Japan();
        }

        return null;
    }
}


 The getCountry() method is responsible for returning the correct class to the Country interface. It takes a parameter which tells it which class to return.

Factory Pattern with Reflection API


Another way to implement the getCountry()method is with the help of the Java reflection API. The following is the implementation of the aforementioned method using reflection api.


package factory;

public class CountryReflectionFactory {

    public static void main(String[] args) {
        Country india = getCountry("country.India");
        india.printCountryCode();   //Prints +91

        Country germany = getCountry("country.Germany");
        germany.printCountryCode(); //Prints +49

        Country japan = getCountry("country.Japan");
        japan.printCountryCode();   //Prints +81
    }

    public static Country getCountry(String pathName) {
        try {
            return (Country) Class.forName(pathName).newInstance();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
            ex.printStackTrace();
            return null;
        }
    }
}


In this example, the fully qualified name i.e., the name of the class with the package details, is sent as a parameter to the getCountry()method which in turn uses the Java Reflection API to generate the classes at runtime.

Factory pattern is probably the most used pattern. It is a very useful to keep classes of the same type together by inheriting a common interface. This feature makes it an important tool to gather simlar together classes and bind them to a single framework.



No comments:

Post a Comment