14-Jul-04 (Created: 14-Jul-04) | More in 'OSCON-2004'

Unified Object Server Factory Pattern: Code Examples

Simple object instantiation

Design your classes


public interface IClass 
{
	public void function1();
}
public class CClass implements IClass
{
	public void function1() {}
}

Use the factory to instantiate them


//first time
IClass i = (IClass)factory.getObject("key1", null);
i.function1();

//second time
//You will get the same object
IClass j = (IClass)factory.getObject("key1", null);
j.function1();

configuration


<key1 classname="CClass">
</key1>

Simple object instantiation with configuration parameters

Design your classes


public interface IClass 
{
	public void function1();
}
public class CClass implements IClass, IInitialize
{
	public void function1() {}
	public void initialize(String key)
	{
		IConfig cfg = apppliation.getIConfig();
		
		//mandatory parameter
		//exception if not found
		String param1 = cfg.getValue(key + ".param1");
		
		//optional paramter
		String param2 = cfg.getValue(key + ".param2", "defaultparam");
	}
}

Use the factory to instantiate them


//first time
IClass i = (IClass)factory.getObject("key1", null);
i.function1();

//second time
//You will get the same object
IClass j = (IClass)factory.getObject("key1", null);
j.function1();

configuration


<key1 classname="CClass">
	<param1>some-value</param1>
</key1>

Above example using IOC


public interface IClass 
{
	public void function1();
}
public class CClass implements IClass
{
	public void function1() {}
	public void CClass(String param1, String param2)
	{
		String p1 = param1;
		String p2 = (param2 == null) ? "defaultValue" : param2;
	}
}

The factory will know from the constructor that it has two parameters and will get them from configuration context knowing that this object is instantiated based on the configuration node of "key1". This pattern in the industry is widely called IOC, inversion of control. In this particular I am using IOC based on a constructor. This can be done based on public fields or setter methods etc as well. Where applicable IoC has some distinct advantages. Particularly the documentation aspect of the required parameters.

Simple object instantiation with configuration object

Design your classes


public interface IClass 
{
	public void function1();
}

public class CClassParameters
{
	public String param1;
	public String param2;
	pubic CompoundParam param3;
}
public class CompoundParam
{
	public String param4;
	public String param5;
}
public class CClass implements IClass, IInitialize
{
	public void function1() {}
	public void initialize(String key)
	{
		IConfig cfg = apppliation.getIConfig();
		CClassParameters params = cfg.fillObject("key1", new CClassParameters());
	}
}

Use the factory to instantiate them


//first time
IClass i = (IClass)factory.getObject("key1", null);
i.function1();

//second time
//You will get the same object
IClass j = (IClass)factory.getObject("key1", null);
j.function1();

configuration


<key1 classname="CClass">
	<param1>value</param1>
	<param2>value<param2>
	<param3>
		<param4>value</param4>
		<param5>value</param5>
	</param3>
</key1>

Simple object instantiation: using IMultiInstance

Design your classes


public interface IClass 
{
	public void function1();
}
public class CClass implements IClass, IMultiInstance
{
	public void function1() {}
}

Use the factory to instantiate them


//first time
IClass i = (IClass)factory.getObject("key1", null);
i.function1();

//second time
//You will get a different newed object
IClass j = (IClass)factory.getObject("key1", null);
j.function1();

configuration


<key1 classname="CClass">
</key1>

Untyped creator pattern

Design your classes


public interface IClass 
{
	public void function1();
}
public class CClass implements IClass
{
	public void function1() {}
}
public class CClassCreator implements ICreator
{
	public Object execute(String key, Object args)
	{
		return new CClass();
	}
}

Use the factory to instantiate them


//first time
IClass i = (IClass)factory.getObject("key1", null);
i.function1();

//second time
//You will get a different object.
//Because the creator is cached and not the product
IClass j = (IClass)factory.getObject("key1", null);
j.function1();

configuration


<key1 classname="CClassCreator">
</key1>

Untyped creator pattern with parameters

Design your classes


public interface IClass 
{
	public void function1();
}
public class CClass implements IClass
{
	public void function1() {}
}
public class CClassCreator implements ICreator, IInitializable
{
	public Object execute(String key, Object args)
	{
		return new CClass();
	}
	
	public void initialize(String key)
	{
		IConfig cfg = apppliation.getIConfig();
		
		//mandatory parameter
		//exception if not found
		String param1 = cfg.getValue(key + ".param1");
		
		//optional paramter
		String param2 = cfg.getValue(key + ".param2", "defaultparam");
	}
}

As susggested one can use IOC here as well.

Use the factory to instantiate them


//first time
IClass i = (IClass)factory.getObject("key1", null);
i.function1();

//second time
//You will get a different object.
//Because the creator is cached and not the product
IClass j = (IClass)factory.getObject("key1", null);
j.function1();

configuration


<key1 classname="CClassCreator">
</key1>

Abstract Typed Factory 1 pattern

Design your classes


public interface IClass 
{
	public void function1();
}
public class CClass implements IClass
{
	public void function1() {}
}
public class AbstractCClassCreator implements ICreator
{
	public Object execute(String key, Object args)
	        throws FactoryException
	{
		if !(args instanceof List)
		{
			throw new FactoryException("Invalid args");
		}
		List lArgs = (List)args;
		String arg1 = (String)lArgs.itemAt(0);
		Integer arg2 = (String)lArgs.itemAt(2);
		
		return createIClass(arg1, arg2.getInt());
	}
	
	static public IClass sCreateIClass(String key, String arg1, int arg2)
	     throws FactoryException
    {
	 	 ArrayList list = new ArrayList();
		 list.add(arg1);
		 list.add(new Integer(arg2));
	     return (IClass)factory.getObject(key,list); 
	}
	
	//Abstract constructor method
	public abstract IClass createIClass(String arg1, int arg2)
	       throws FactoryException;
}

Now I can create the CClassCreator as follows in a typed manner


public class CClassCreator extends AbstractCClassCreator
{
	//Abstract constructor method
	public abstract IClass createIClass(String arg1, int arg2)
	       throws FactoryException
	{
		return new CClass();
	}		   
}

Use the Abstract typed factory to instantiate them


//first time
IClass i = AbstractCClassCreator.sCreateIClass("key1", "dddd",10);
i.function1();

//second time
//You will get a different object.
//Because the creator is cached and not the product
IClass j = AbstractCClassCreator.sCreateIClass("key1", "dddd",10);
j.function1();

configuration


<key1 classname="CClassCreator">
</key1>

Abstract Typed Factory 2 pattern

This is a variation on the above where the class directly supports not only its usage interface but its construction interface as well. In this scenario here is what happens to the CClass:


public class CClass extends AbstractCClassCreator implements IClass
{
	//Abstract constructor method
	//This method is almost like a constructor
	public abstract IClass createIClass(String arg1, int arg2)
	       throws FactoryException
	{
		return new CClass();
	}		   
	
	//other ICLass methods
	public void funtion1();
}

And the configuration is rewritten to use the CClas itself


<key1 classname="CClass">
</key1>

Abstract Typed Delegate pattern

Design your classes



public interface IClass 
{
	public void function1();
}

public class AbstractDelegate implements ICreator
{
	public Object execute(String key, Object args)
	        throws FactoryException
	{
		if !(args instanceof List)
		{
			throw new FactoryException("Invalid args");
		}
		List lArgs = (List)args;
		String arg1 = (String)lArgs.itemAt(0);
		Integer arg2 = (String)lArgs.itemAt(2);
		
		return delegateExecute(arg1, arg2.getInt());
	}
	
	static public IClass sDelegateExecute(String key, String arg1, int arg2)
	     throws FactoryException
    {
	 	 ArrayList list = new ArrayList();
		 list.add(arg1);
		 list.add(new Integer(arg2));
	     return (IClass)factory.getObject(key,list); 
	}
	
	//Abstract constructor method
	public abstract IClass delegateExecute(String arg1, int arg2)
	       throws FactoryException;
}

public class MyDelegate1 extends AbstractDelegate
{
	public IClass delegateExecute(String arg1, int arg2)
	       throws FactoryException
    {
			//do some work and return IClass
	}
}

public class MyDelegate2 extends AbstractDelegate
{
	public IClass delegateExecute(String arg1, int arg2)
	       throws FactoryException
    {
			//do some other work and return IClass
	}
}

How to use the above delegates


//will call MyDelegate1.function1()
IClass i = AbstractDelegate.sDelegateExecute("key1", "dddd",10);
i.function1();

//will call MyDelegate2.function1()
IClass j = AbstractDelegate.sDelegateExecute("key2", "dddd",10);
j.function1();

Supporting Configuration


<key1 classname="MyDelegate1">
</key1>

<key2 classname="MyDelegate2">
</key1>

References

1. Unified Abstract Configuration Pattern Examples

2. General Introduction to Server side Patterns

3. OSCON 2004 Summary page for Server side patterns session