有没有一种简单的方法来组合 Java 中的工厂?

Is there a simple way to combine Factories in Java?

假设我有工厂接口 classes FactoryAFactoryB 分别具有用于生成类型 AB 的对象的方法,并假设我有这些接口的实现。现在假设我需要一个实现这两个接口的工厂 class FactoryAB,即生成 AB。有没有一种简单的方法来组合接口 FactoryAFactoryB 的实现以获得 FactoryAB?

编辑: 这是由于 class 需要大量工厂来生产大量不同对象的情况。在这种情况下,在我看来,只有一个 large 工厂可以生产所有需要的组件,而不必跟踪许多 small 工厂更方便] 工厂。

主要目标是不必编写太多代码即可实现此目的。也许,其他一些模式更适合这种情况?

编辑2: 从本质上讲,我想摆脱像这样臃肿的代码:

public class Consumer {
 FactoryA factoryAImpl;
 FactoryB factoryBImpl;
 // ...
 FactoryY factoryYImpl;
 FactoryZ factoryZImpl;

 public Consumer(FactoryA factoryA, FactoryB factoryB, ..., FactoryZ factoryZ) {
   // ...
 }
 //...
}

compact/simple 代码如下:

public class Consumer {
 FactoryAtoZ factoryAtoZImpl;

 public Consumer(FactoryAtoZ factoryAtoZ) {
   // ...
 }
 //...
}

你可以用组合来做到这一点:

public class FactoryAB implements FactoryA, FactoryB
{
   FactoryA factoryAImpl = new FactoryAImplementor();
   FactoryB factoryBImpl = new FactoryBImplementor();

   public ObjectA getObjectA()  {
        return factoryAImpl.getObjectA();
   }

   public ObjectB getObjectB()  {
        return factoryBImpl.getObjectB();
   }
}

您可以使用复合概念和工厂方法模式来组合FactoryAFactoryB接口。假设您有一个公共接口 ABpublic A getA() FactoryA 的工厂方法和 public B getB() FactoryB 的工厂方法:

public class ABFactory implements FactoryA, FactoryB {
    public AB GetAB(InterfaceType type) {
        AB implementation = null;
        switch (type)
        {
            case InterfaceType.AType:
                implementation = getA();
                break;
            case InterfaceType.BType:
                implementation = getB();
                break;
            default:
                break;
        }
        return implementation;
    }
   public A getA() {
      return new FactoryAImpl().getA();
   }

   public B getB() {
      return new FactoryBImpl().getB();
   }

}

假设

public enum InterfaceType {
    AType,
    BType
}

可以通过动态生成代理并将方法调用委托给具体对象来做到这一点当且仅当您有一个确定将其移交给哪个代表的可靠方法。

首先你需要一个结合现有工厂的接口

public interface FactoryAB extends FactoryA, FactoryB {
}

(注意缺少方法)

然后你需要创建代理

    DelegatingHandler handler = new DelegatingHandler(new ConcreteFactoryA(), new ConcreteFactoryB());
    FactoryAB factoryAb = (FactoryAB)Proxy.newProxyInstance(handler.getClass().getClassLoader(), new Class[]{FactoryAB.class}, handler);

最后 InvocationHandler 为您进行实际的方法拦截

public class DelegatingHandler implements InvocationHandler {
    private final List<Object> factoryDelegates;

    public DelegatingHandler(Object ... factories) {
        factoryDelegates = Arrays.asList(factories);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        for (Object factory : factoryDelegates) {
            Method[] declaredMethods = factory.getClass().getDeclaredMethods();
            for (Method declaredMethod : declaredMethods) {
                if (declaredMethod.getReturnType().equals(method.getReturnType())) {
                    return method.invoke(factory, args);
                }
            }
        };
        return null;
    }
}

这是通过提供要委托给的具体工厂列表来工作的,并且在每次方法调用时都会查看这些工厂以找到具有与 return 类型匹配的方法的工厂。当它找到一个时,它将调用您在委托工厂上调用的方法和 return 无论它 returns.

我怀疑您可能需要进行更多复杂的检查才能找到合适的委托人,但只有您自己知道。

使用它,您只需添加到 FactoryAB 接口并将所需的委托注入 DelegatingHandler,即可将新工厂添加到您的委托中,无需进一步的工作。

您应该注意,使用此方法后,您的所有调用现在都通过反射而不是直接方法调用进行路由