Java8供应商,是可选的消费者

时间:2015-03-26 07:39:33

标签: java functional-programming java-8

我只能用这个例子来解释这个。

我们有主要课程AppServer。它还包含几个应用程序范围的组件。

AppServer app = new AppServer(config, ...);

现在我们需要提供一个供应商,作为某些Foo实例的工厂。将在循环中多次调用此供应商以创建一些Foo个实例。通过使用供应商,我们允许用户提供他们自己的Foo实施。请注意,Foo不是我们的类,我们无法更改它。

唯一的问题是Foo需要应用程序中的某些组件。需要将它们注入/提供给FooImpl

这可以这样写:

app.setFooSupplier(() -> new FooImpl(app.component()));

这对我来说有点难看,并想知道是否有更好的方法来做到这一点?到目前为止,这里有一些想法......

(1)在使用供应商后注入依赖关系(IoC方式)。

依赖关系由setter定义。所以我们在sudo中有类似的东西(在AppServer内):

Foo foo = fooSupplier.get();
maybeInject(foo, component1);
maybeInject(foo, component2);
...

注入的组件取决于setter是否存在。或者,我们可以使用Component1Aware接口,并执行相同的操作:

Foo foo = fooSupplier.get();
if (foo instanceof Component1Aware) {
    ((Component1Aware)foo).setComponent1(component1);
}
...

基本相同。

我想在构造函数中有依赖项,所以要表达它们需要设置。

(2)使用可选消费者

Supplier创建一个与FooImpl同时Consumer AppServer的{​​{1}}个实例。类似的东西:

public class FooImplSupplier implements Supplier<Foo>, Consumer<AppServer> {
    ...
}

然后我们可以非常轻松地注册该供应商:

app.setFooSupplier(new FooImplSupplier());

在供应商创建实例(AppServer)后,我们执行以下操作:

Foo foo = fooSupplier.get();
if (foo instanceof Consumer) {
    ((Consumer)foo).accept(this);
}

Wdyt?

2 个答案:

答案 0 :(得分:2)

我总是倾向于通过构造函数(或静态工厂方法)传递强制设置。我更喜欢的IoC风格是

app.setFooSupplier(() -> new FooImpl(app.component()));

或者如果app.component()每次返回相同的内容,您可以编写以下内容。

Component comp = app.component();
app.setFooSupplier(() -> new FooImpl(comp));

这是迄今为止最简单也最难出错的问题。例如你不能传递0或多次参数,或者在初始化之前尝试使用供应商。

答案 1 :(得分:2)

向供应商提供上下文信息并不罕见。您遇到的问题是您已在Supplier界面上修复,这会分散您对简单解决方案的注意力。不应尝试将SupplierConsumer结合使用,而应使用Function

void setFooProvider(Function<AppServer,Foo> f) {
  this.fooProvider=Objects.requireNonNull(f);
}
// …
// in a method within the same class:
    Foo foo=fooProvider.apply(this);

呼叫者:

app.setFooProvider(appArg -> new FooImpl(appArg.component()));

我将方法的名称从…Supplier更改为…Provider,以明确提供的参数的作用对特定interface并不紧密。无论适合什么情况,您都可以使用SupplierFunctionBiFunction或自定义interface

现在指定的提供程序使用它的参数,并且不会从其周围的上下文中捕获值,这使得它不变(并且当前实现它将是一个单例)。

请注意,仍然可以实现仅忽略参数的提供程序函数,因此基于Supplier的解决方案的原始功能不会丢失。