Reputation: 2957
I am making a factory for my domain objects. Domain objects are prototype objects so they get instantiated quite frequently when the business logic runs. Following is the design:
1) Some domain interfaces and classes:
public interface FirstDomainInterface {}
public class FirstDomainClass implements FirstDomainInterface {
private String firstName;
private int phoneNumber;
public FirstDomainClass(String firstName, int phoneNumber) {
super();
this.firstName = firstName;
this.phoneNumber = phoneNumber;
}
public interface SecondInterface {}
public class SecondDomainClass implements SecondInterface {
private long accountNumber;
private BigDecimal balance;
public SecondDomainClass(long accountNumber, BigDecimal balance) {
super();
this.accountNumber = accountNumber;
this.balance = balance;
}
2) Interface declaring method which returns constructor for type of object required from the factory
public interface ObjectConfig {
public Constructor<?> getConstructor() throws NoSuchMethodException, SecurityException;
}
3) Implementations of Interface declared in second point
public enum FirstModuleConfig implements ObjectConfig {
FirstTypeObject {
@Override
public Constructor<?> getConstructor() throws NoSuchMethodException, SecurityException {
Constructor<FirstDomainClass> constructor = FirstDomainClass.class.getConstructor(String.class, int.class);
return constructor;
}
}
}
public enum SecondModuleConfig implements ObjectConfig {
SecondTypeObject {
@Override
public Constructor<?> getConstructor() throws NoSuchMethodException, SecurityException {
Constructor<SecondDomainClass> constructor = SecondDomainClass.class.getConstructor(long.class, BigDecimal.class);
return constructor;
}
}
}
4) The Factory which instantiates the object
public class Factory {
public Object createInstance(ObjectConfig config, Object...args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return config.getConstructor().newInstance(args);
}
}
5) Finally using the factory:
public class FactoryTest {
@Test
public void test() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Factory factory = new Factory();
FirstDomainInterface firstTypeObject = (FirstDomainInterface) factory.createInstance(FirstModuleConfig.FirstTypeObject,"myName",12345);
SecondInterface secondTypeObject = (SecondInterface)factory.createInstance(SecondModuleConfig.SecondTypeObject, 123455232l,BigDecimal.ZERO);
}
}
How does this look?
Potential advantages which I see:
1) For each new interface/class I make, I just need to declare it's constructor in one of the Enum implementing ObjectConfig Interface
2) Looks a clean design to me. I won't have to implement a full fledged factory for all my domain objects. Just needed to implement a single method which returns constructor to be used for instantiation.
3) Can inject this single Factory to all services which need to create my domain objects
Disadvantages I suspect:
1) Potential runtime exceptions due to class cast, parameters mismatch etc.
2) Slow due to use of reflection?
Note that this is meant to be used for instantiating prototype domain/business objects by the service layer. For singleton service and controller beans, I am using Spring Container which gets those beans ready during startup.
Thanks!
Upvotes: 0
Views: 116
Reputation: 2605
Well there are several advantages of using static factories. Using factory to create classes seems a good approach.
However I would make the following comments that you could consider in your implementation.
Consider restricting public constructors to package private and allow only Factory methods. The factory should be in the same package. So you could also make an instance controlling factory and that you enforce consistent usage of the factory methods. Otherwise fellow programmers in your team (or you in the future) could end up using both factories and constructors.
Using functions such as this:
public Object createInstance(ObjectConfig config, Object...args)
You save some typing time during programming but you loose a lot of the checks your compiler would make in compile time and maybe you increase the chances for more runtime errors. This practice should be avoided in general.
There is a good description about the factory methods in the first section of Effective Java Second Edition of Joshua Bloch. You could check it before you proceed.
These are some generic remarks however the path you take in your design is related to the purpose that your application will serve.
I would propose something like that:
public class Factory{
public InterfaceA createNewInterfaceA(int argumentInt,String argumentString){
return new ClassImplementingInterfaceA();
}
public InterfaceA createNewInterfaceA(int argumentInt,double argumentDouble){
return new ClassImplementingInterfaceA(argumentInt,argumentDouble);
}
}
...similar for all other interfaces
Upvotes: 0