davidraviv
5/13/2014 - 5:48 AM

Simple singleton factory to create class implementing Action interface.The constructor for creating the class is cached internally to reuse

Simple singleton factory to create class implementing Action interface.The constructor for creating the class is cached internally to reuse in the next invokation.In the className implementation is missing, this factory returns null.* Action is proprietary interface, can be replaced with any other interface. JsonNode is the constructor input for Action.

package com.company.product

import com.fasterxml.jackson.databind.JsonNode;
import org.apache.log4j.Logger;

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

/**
 * A singleton cached factory to create Actions
 * Created by davidraviv on 13/5/14.
 */
public class ActionFactory {
	private static ActionFactory ourInstance = new ActionFactory();
	private static final Logger logger = Logger.getLogger(ActionFactory.class);

	// cache to hold Action constructors
	private Map<String, Constructor<?>> ctorCache = new HashMap<>();

	public static ActionFactory getInstance() {
		return ourInstance;
	}

	private ActionFactory() {
		// hide default constructor
	}

	/**
	 * Create a new instance of Action 
	 * @param className Action class name
	 * @param actionData actionData to initiate the Action with
	 * @return Returns an instance of Action initiated with actionData. Will return null in case of error.
	 */
	public Action buildAction(String className, JsonNode actionData) {

		Action action = null;

		try {
			// try to find the constructor in the cache
			Constructor<?> ctor = ctorCache.get(className);

			if (ctor == null) {
				// constructor was not found in cache, create a new one and keep it for later
				Class<?> clazz = Class.forName(className);
				ctor = clazz.getConstructor(JsonNode.class);
				ctorCache.put(className, ctor);
			}
			// create the Action using the ctor
			action = (Action) ctor.newInstance(actionData);

		} catch (Exception e) {
			logger.error("Failed to initiate class " + className + ": " + e.getMessage(), e);
		}

		return action;
	}
}