【问题标题】:Does this design for Factory of Domain objects make sense?域对象工厂的这种设计有意义吗?
【发布时间】:2015-10-09 13:27:04
【问题描述】:

我正在为我的域对象创建一个工厂。领域对象是原型对象,因此在业务逻辑运行时它们会被频繁地实例化。以下是设计:

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) 对于我创建的每个新接口/类,我只需在 Enum 实现 ObjectConfig 接口之一中声明它的构造函数

2) 在我看来是一个简洁的设计。我不必为我的所有域对象实现一个完整的工厂。只需要实现一个返回构造函数以用于实例化的方法。

3) 可以将这个工厂注入所有需要创建我的域对象的服务

我怀疑的缺点:

1) 由于类转换、参数不匹配等可能导致的运行时异常。

2) 由于使用反射而变慢?

请注意,这意味着服务层用于实例化原型域/业务对象。 对于单例服务和控制器 bean,我使用的是 Spring Container,它在启动期间准备好这些 bean。

谢谢!

【问题讨论】:

  • 这个问题最好是codereview.stackexchange.com。我首先要问的问题是“你为什么要这样做?”
  • 基本工厂出了什么问题,或者,看哪,只是new instance()。为什么这个装置...
  • @M.Deinum 域类太多。这样,实例化逻辑将在一个地方。每当我创建一个新类时,我只需要注册构造函数。如果我使用 SimpleFactory,那么对于不同类型的对象将会有太多的简单工厂,然后根据需要在不同的地方注入这些不同的工厂将是另一项任务。使用它,我只需要在每个服务类中注入这个单一的工厂。这个思考过程有什么问题吗?
  • 就使用“new”而言,假设我创建了一个名为 FirstDomainClassTwo 的新类,它实现了 FirstDomainInterface,并希望 FirstDomainInterface 的所有实例都属于这个 FirstDomainClassTwo 类。然后我只需要更改 FirstType Enum 的 getConstructor() 方法中的构造函数,它将反映在整个应用程序中。
  • 我仍在努力了解您要解决的实际 /problem/ 是什么

标签: java dependency-injection factory factory-pattern


【解决方案1】:

嗯,使用静态工厂有几个优点。使用工厂创建类似乎是一个不错的方法。

但是,我会制作您可以在实施中考虑的以下 cmets。

  1. 考虑将公共构造函数限制为封装私有并仅允许工厂方法。工厂应该在同一个包中。因此,您还可以创建一个实例控制工厂,并强制使用工厂方法。否则,您团队中的其他程序员(或未来的您)最终可能会同时使用工厂和构造函数。

  2. 使用如下函数:

public Object createInstance(ObjectConfig config, Object...args)

您在编程期间节省了一些打字时间,但您丢失了编译器在编译时进行的大量检查,并且可能会增加更多运行时错误的机会。一般应避免这种做法。

  1. 性能肯定更差,所以如果你必须维护你的代码,为什么不为每个类添加一个专用的工厂方法。这只是对包私有构造函数的委托调用。易读易写。

在 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

【讨论】:

  • 是的,使用简单工厂绝对是一种选择。我正在探索更简洁、更短的东西的可能性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-30
相关资源
最近更新 更多