Patterns with Spring
Posted by ice09 on August 4, 2008
There are several articles about Patterns with Spring in “Enterprise” context, ie. on the server side and simulating more or less typical JEE Patterns. These are important, however, Spring has its use in small, batch and client side apps as well.
Therefore, it makes sense to recall old school Design Patterns, which can be used independently of the programming context, just to reuse good solutions for old problems.
However, working with Spring, it’s easy to recognize that Patterns must be adapted to Spring, since some of them do not make sense when working with Spring.
I will elaborate the most important and famous ones here in the context of Spring usage.
For two reasons, the Factory Method Pattern is not really useful in the Spring context:
- Spring’s BeanFactory implements a kind of Factory Pattern itself. It is easy to use different BeanFactories and therefore create different beans according to context. For example, using several XML-configurations and instantiating them in different ApplicationContexts gives you several bean factories configured with XML.
- Since with Spring injecting different beans is done by XML-configurations and pseudo-Singletons are used, the advantage of having a single point of changing bean instantiation is inherent to Spring.
Nevertheless, I implemented the almost original Factory Method Pattern below.
Usually, the beans-factory-lookup-method-injection is referred as the factory method implementation in spring. Thought this is certainly true with respect to the actual pattern, it is difficult to see the advantage of this approach in contrast to just injecting a bean. This is even more transparent and there is no magic in it.
To actually make use of creating different objects, I made up the following scenario, which allows for creating different objects during runtime. There is nothing special in it, just plain usage of Spring, magic excluded.
package sample.factory;
public enum Type {
FIRST, SECOND;
}
An interface to identifying the objects:
package sample.factory;
public interface ClassType {
Type getId();
}
First type of object:
package sample.factory;
public class FirstType implements ClassType {
@Override
public Type getId() {
return Type.FIRST;
}
@Override
public String toString() {
return getId().toString();
}
}
Second type of object:
package sample.factory;
public class SecondType implements ClassType {
@Override
public Type getId() {
return Type.SECOND;
}
@Override
public String toString() {
return getId().toString();
}
}
The factory itself, objects will be injected:
package sample.factory;
import java.util.Map;
public class FactorySample {
private Map<Type, ClassType> identifiers;
public void setConcreteClasses(Map<Type, ClassType> i) {
this.identifiers = i;
}
public ClassType createClassOfType(Type type) {
switch (type) {
case FIRST : return identifiers.get(type);
case SECOND : return identifiers.get(type);
default : return null;
}
}
}
Main class which retrieves factory bean and creates a object of second type:
package sample.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext app = new ClassPathXmlApplicationContext("beans.xml");
FactorySample factory = (FactorySample) app.getBean("factory");
ClassType i = factory.createClassOfType(Type.SECOND);
System.out.println(i);
}
}
Finally, the spring config (entry key Strings are converted automagically by Spring):
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="factory" class="sample.factory.FactorySample"> <property name="concreteClasses"> <map> <entry key="FIRST"> <ref local="FirstType" /> </entry> <entry key="SECOND"> <ref local="SecondType" /> </entry> </map> </property> </bean> <bean id="FirstType" class="sample.factory.FirstType"/> <bean id="SecondType" class="sample.factory.SecondType"/> </beans>