我正在为我的域对象制作工厂。域对象是原型对象,因此在业务逻辑运行时它们会经常被实例化。以下是设计:
1)一些域接口和类:
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)接口声明方法,它返回工厂所需对象类型的构造函数
public interface ObjectConfig {
public Constructor<?> getConstructor() throws NoSuchMethodException, SecurityException;
}
3)在第二点声明的接口的实现
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)实例化对象的工厂
public class Factory {
public Object createInstance(ObjectConfig config, Object...args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return config.getConstructor().newInstance(args);
}
}
5)最后使用工厂:
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);
}
}
这看起来怎么样?
我看到的潜在优势:
1)对于我创建的每个新接口/类,我只需要在其中一个实现ObjectConfig接口的Enum中声明它的构造函数
2)给我一个干净的设计。我不必为我的所有域对象实现一个完整的工厂。只需要实现一个返回构造函数用于实例化的方法。
3)可以将此单个Factory注入需要创建域对象的所有服务
我怀疑的缺点:
1)由于类强制转换,参数不匹配等导致的潜在运行时异常。
2)由于使用反射而变慢?
请注意,这意味着用于通过服务层实例化原型域/业务对象。对于单例服务和控制器bean,我使用的是Spring Container,它可以在启动时准备好这些bean。
谢谢!
答案 0 :(得分:0)
使用静态工厂有几个好处。使用工厂创建类似乎是一种很好的方法。
但是,我会在您的实施中提出以下意见。
考虑将公共构造函数限制为包私有,并仅允许使用Factory方法。工厂应该在同一个包装中。因此,您还可以创建一个实例控制工厂,并强制一致使用工厂方法。否则,团队中的其他程序员(或将来的某些程序员)最终可能会同时使用工厂和构造函数。
使用以下功能:
public Object createInstance(ObjectConfig config,Object ... args)
您在编程期间节省了一些打字时间,但是您在编译时会丢失很多编译器所做的检查,并且可能会增加更多运行时错误的机会。一般来说,这种做法应该避免。
Joshua Bloch的Effective Java Second Edition第一部分中有关于工厂方法的很好的描述。你可以在继续之前检查它。
这些是一些通用的注释,但是您在设计中采用的路径与应用程序的服务目的有关。
我会提出类似的建议:
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