java - 如何用方法注入(inject)替换装饰器中的构造函数注入(inject)以获得链接并使现有代码按原样工作?

标签 java

我们的代码如下所示:

Service<E,F> pipeline = new MyServiceDecorator2(new MyServiceDecorator1(new MyService()));

然后执行为 F f = pipeline.apply(new E("E"))

我们希望它的内容如下:

Service<A,B> myService = new MyService();
// Service<C,D>
MyServiceDecorator1 myServiceDecorator1 = new MyServiceDecorator1();
// Service<E,F>
MyServiceDecorator2 myServiceDecorator2 = new MyServiceDecorator2();

Service<E,F> pipeline = myServiceDecorator2.andThen(myServiceDecorator1).andThen(myService);

// This should still be doable i.e., the end goal
F f = pipeline.apply(new E("E"));

我们尝试了各种技巧,但无法使返回类型正确排列。上面的代码会抛出一个错误 - 我们只是手动将 andThen 添加到每个 Decorator 类中,只是为了了解流程,如下所示:

public <J,K> Service andThen(Service<J,K> next) {
 this.service = next;
 return next;
}

这将返回链中“下一项”的类型。我尝试了一些使用 next/prev 引用/指针的技巧来沿着链向上移动,但似乎没有任何效果。这可能吗?

这是一个REPL显示带有打印语句的代码,显示装饰器的进展。

上下文:我们有相当多的代码可以简化为“装饰器”来实现“管道和过滤器”模式,这样我们就可以提供一个基本的“框架”,让开发者能够运用相同的模式/思维来解决相同的问题,而不是复制/面食或重新发明轮子。以上是我们想要实现的目标的“示例”。我们计划将其转换为泛型,但目前存在重复的代码。

最佳答案

编辑:正在研究另一种方法(我认为它有同样的问题......)

嗯,你无法真正获得你想要的东西,你需要在一些东西上进行权衡。
在本例中,它位于 apply 方法上,该方法必须接受 Domain

发生这种情况是因为包装的 Service 未在构造时设置,因此无法 100% 键入。

interface Service<A extends Domain, B extends Domain> {
    B apply(final Domain a);
    Service<A, B> andThen(final Service<? extends Domain, ? extends Domain> service);
}
<小时/>
class MyService implements Service<A, B> {
    private Service<? extends Domain, ? extends Domain> wrapped;

    @Override
    public B apply(final Domain a) {
        return new B(a.name + "->B");
    }

    @Override
    public Service<A, B> andThen(final Service<? extends Domain, ? extends Domain> wrapped) {
        this.wrapped = wrapped;
        return this;
    }
}
<小时/>
class MyServiceDecorator1 implements Service<C, D> {
    private Service<? extends Domain, ? extends Domain> wrapped;

    @Override
    public D apply(final Domain input) {
        // C->A
        Domain a = new A(input.name + "->A");
        // get B
        Domain b = this.wrapped.apply(a);
        // B->D
        return new D(b.name + "->D");
    }

    public Service<C, D> andThen(final Service<? extends Domain, ? extends Domain> wrapped) {
        this.wrapped = wrapped;
        return this;
    }
}
<小时/>
class MyServiceDecorator2 implements Service<E, F> {
    private Service<? extends Domain, ? extends Domain> wrapped;

    @Override
    public F apply(final Domain input) {
        // E->C
        Domain c = new C(input.name + "->C");
        // get D
        Domain d = this.wrapped.apply(c);
        // D->F
        return new F(d.name + "->F");
    }

    @Override
    public Service<E, F> andThen(final Service<? extends Domain, ? extends Domain> wrapped) {
        this.wrapped = wrapped;
        return this;
    }
}
<小时/>
public static void main(String[] args) {
    final Service<A, B> myService = new MyService();
    MyServiceDecorator1 myServiceDecorator1 = new MyServiceDecorator1();
    MyServiceDecorator2 myServiceDecorator2 = new MyServiceDecorator2();

    final Service<E, F> efService =
            myServiceDecorator2.andThen(myServiceDecorator1)
                               .andThen(myService);

    // This should still be doable i.e., the end goal
    F f = efService.apply(new E("E"));
    System.out.println(f.name);
}

我无法做得更好,因为 Java 的泛型功能有限。

<小时/>

结束语:字节码生成是您的 friend 。

关于java - 如何用方法注入(inject)替换装饰器中的构造函数注入(inject)以获得链接并使现有代码按原样工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55150648/

相关文章:

java - 如何立即关闭executorservice中的所有线程?

JLIST 上的 Java 空指针异常

java - 为什么我在使用 G1GC 时会变高 `Ref Proc` 次

java - 如何在 Java 中从 JSON 中提取 JSONArray 和 JSONObject

java - 为什么这不是一个模棱两可的电话? (可变参数)

java - Grails 编码参数发布请求

java - 使用 tomcat 7 从项目中删除 SSL 证书

java - 使用 JXL 关闭 Excel 中的网格线

java - html 中 Java 代码的语法高亮

java - 从字符串中删除特殊字符