代码之家  ›  专栏  ›  技术社区  ›  PhD Gangstead

我如何用方法注入取代decorators中的构造函数注入,以获得链接并使现有代码按原样工作?

  •  0
  • PhD Gangstead  · 技术社区  · 7 年前

    我们的代码如下所示:

    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 用一个print语句显示代码,该语句显示通过decorators的进程。

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

    0 回复  |  直到 7 年前
        1
  •  1
  •   LppEdd    7 年前

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

    嗯,你不可能真正得到你想要的,你需要在某些东西上进行权衡。
    在这种情况下 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仅限于泛型功能。


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