如何使用方法注入来替换装饰器中的构造函数注入,以实现链接并让现有代码按原样工作?

时间:2019-03-13 20:26:45

标签: 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,其中显示代码,并带有打印语句,显示通过装饰器的进度。

上下文:我们有大量的代码可以简化为“装饰器”,以实现“管道和过滤器”模式,以便我们提供基本的“框架”,使开发人员能够运用相同的图案/思路解决相同的问题,而不是复制/粘贴或重新发明轮子。以上是我们要实现的目标的“示例”。我们计划将其转换为泛型,但目前有重复的代码。

1 个答案:

答案 0 :(得分:1)

编辑:正在尝试另一种方法(我认为它具有相同的问题...)

嗯,您无法真正获得想要的东西,需要权衡一些东西。
在这种情况下,它是使用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的泛型功能受到限制。


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