September 4, 2011

How to implement Factory Pattern in Spring Framework ?

Factory design pattern is the simplest creational design pattern. Spring Framework creates and manages life-cycle of multiple beans and provides features like dependency injection. This post documents using Factory Pattern in Spring.

Building Blocks of Implementation - Taking example of Ford Car

Common Interface : A common interface is required to signify an abstract product from factory.
package org.pattern.factory;

public abstract class Ford {

    public abstract String getEngineType();

    public String getCar() {
        return this.getClass().getSimpleName();
    }
}

Concrete Car:
package org.pattern.factory.concrete;

import org.pattern.factory.Ford;

public class Endeavour extends Ford {

    @Override
    public String getEngineType() {
        return "DIESEL";
    }
}

Factory Class: This looks for implementations of Ford.class declared in spring configuration and adds them to HashMap. Factory method to return concrete object uses this HashMap.
package org.pattern.factory;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class FordFactory implements ApplicationContextAware {

    private static ApplicationContext mApplicationContext;

    private static Map<String, String> processorBeanMap = new HashMap<String, String>();

    public static Ford getFord(String carName) throws Exception {

        if (processorBeanMap.size() == 0) {
            throw new Exception("No Car in configuration. Check Spring Context");
        } else {
            String beanName = processorBeanMap.get(carName);

            if (beanName == null) {
                throw new Exception(
                        "No Matching Car found. Check Spring Context");
            }

            Ford bean = (Ford) mApplicationContext.getBean(beanName);

            return bean;
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {

        mApplicationContext = applicationContext;

        Map<String, Ford> processorMap = mApplicationContext
                .getBeansOfType(Ford.class);

        if (processorMap.isEmpty()) {
            Error noProcessorError = new Error(
                    "No Car configured. Check Spring Context");
            throw noProcessorError;
        }

        Set<Entry<String, Ford>> processorEntrySet = processorMap.entrySet();

        Iterator<Entry<String, Ford>> iterator = processorEntrySet.iterator();

        while (iterator.hasNext()) {
            Entry<String, Ford> entry = iterator.next();

            processorBeanMap.put(entry.getValue().getCar(), entry.getKey());
        }
    }
}

Spring Configuration File:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean name="CarFactory" class="org.pattern.factory.FordFactory" />

    <bean name="Endevour" class="org.pattern.factory.concrete.Endeavour" />
</beans>

JUnit Test Case:
package org.pattern.factory.test;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.pattern.factory.Ford;
import org.pattern.factory.FordFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class FactoryTest {

    @Test
    public void testFactory() throws Exception {
        Ford car = FordFactory.getFord("Endeavour");
        System.out.println(car.getCar() + " is of Type " + car.getEngineType());
    }

}

Output:

Endeavour is of Type DIESEL

This is a very simple example of using factory pattern in Spring.

Above post uses Syntax Highlighter from tohtml.com




3 comments:

Michelle said...

Nice example! Thanks!!!

Anonymous said...

Helps me a lot. Thanks!

Anonymous said...

Another alternative approach is to use Spring Service Locator Factory Bean