2016-12-30 67 views
1

假设我有一个直观的问题,使用递归最好解决。如何避免将一个上下文传递给一堆方法调用?

我也想使用依赖注入使代码testeable:现在

class Foo { 

    Bar bar; 

    Foo(Bar bar) { 
     this.bar = bar; 
    } 

    ResultType doFoo() { 
     ...stuff... 
     bar.doBar(); 
    } 

} 

class Bar { 

    Baz baz; 

    Bar(Baz baz) { 
     this.baz = baz; 
    } 

    ResultType doBar() { 
     ...stuff... 
     baz.doBaz(); 
    } 
} 

class Baz { 

    Foo foo; 

    Baz(Foo foo) { 
     this.foo; 
    } 

    ResultType doBaz() { 
     if (foo is needed) { 
      foo.doFoo(smaller problem) 
     } else { 
      ...stuf... 
     } 
    } 
} 

,如果巴兹wan't依赖于富,你可能只是这样做:

Foo foo = new Foo(new Bar(new Baz())); 

Baz可以带任何Foo,所以如果它只是得到顶端的那个就没有问题,从而形成一个循环。

(JVM可以负责循环IIRC)。只有Baz可以确定它是否需要Foo。

以可测试的方式让Foo进入Baz的最简洁方法是什么?

是否将Foo参数添加到我的唯一选项doBaz()? (言下之意是美孚需要通过“本”,以doBar,然后把它传递给doBaz,等...或者是有更好的办法?)

编辑:

也许问题的描述的确会有用。

该算法基本上是一个编译器,它将代码作为输入并输出代表代码含义的数据结构。这种数据结构本质上是高度递归的。

但是,代码中可能存在不清晰(认为未声明的方法)。造成这个问题的原因是,与大多数编译器不同,这不应该简单地在用户身上呕吐一堆错误,而是向用户提供一个选项来输入更多的代码。

基本上,编译器会暂时停止编译“主”代码,并开始编译这个由用户提供的新代码。在此之后,它会将产生的数据结构附加到“主”数据结构。

如果在用户提供的这个代码中有更多的非文字,它将再次允许用户澄清。

基本上,实现代码不完整的组件(由Baz代表)必须调用“main”组件(Foo)来开始编译用户提供的代码。

+0

如果您更详细地描述实际问题,这可能会有帮助。很可能有一种不同的分解方式会减少周期性。 – chrylis

+0

好的,完成了。只是这个过程本身是以用户可见的方式递归的,所以也许很难摆脱递归算法本身。 – user1582024

+0

我有一种模糊的观点,认为访客可能是更好的方法。 – chrylis

回答

0

一些其他选项:

  1. 如果Foo是单(即在程序中只有一个实例),那么你可以在Foo中有一个静态方法返回这样的实例

  2. 你可以保留对“前一个”对象的引用,并使用它从Baz中遍历回来:

    类Foo {

    Bar bar; 
    
    Foo(Bar bar) { 
        this.bar = bar; 
        bar.setFoo(this); 
    } 
    
    ResultType doFoo() { 
        ...stuff... 
        bar.doBar(); 
    } 
    

    }

    类酒吧{ 美孚FOO; Baz baz;

    Bar(Baz baz) { 
        this.baz = baz; 
        baz.setBar(this); 
    } 
    
    void setFoo(Foo foo) { 
        this.foo = foo; 
    } 
    
    Foo getFoo() { 
        return foo; 
    } 
    
    ResultType doBar() { 
        ...stuff... 
        baz.doBaz(); 
    } 
    

    }

    类巴兹{ 酒吧巴; Foo foo;

    Baz(Foo foo) { 
        this.foo; 
    } 
    
    void setBar(Bar bar) { 
        this.bar = bar; 
    } 
    
    ResultType doBaz() { 
        if (foo is needed) { 
         bar.getFoo().doFoo(smaller problem) 
        } else { 
         ...stuf... 
        } 
    } 
    

    }

0

你可以seperately构建这些对象,然后海誓山盟登记。

最简单的形式是这样的:

class Foo { 

    Bar bar; 

    void setBar(Bar bar) { 
     this.bar = bar; 
    } 

    ResultType doFoo() { 
     ...stuff... 
     bar.doBar(); 
    } 

} 

class Bar { 

    Baz baz; 

    void setBaz(Baz baz) { 
     this.baz = baz; 
    } 

    ResultType doBar() { 
     ...stuff... 
     baz.doBaz(); 
    } 
} 

class Baz { 

    Foo foo; 

    void setFoo(Foo foo) { 
     this.foo; 
    } 

    ResultType doBaz() { 
     if (foo is needed) { 
      foo.doFoo(smaller problem) 
     } else { 
      ...stuf... 
     } 
    } 
} 

然后,构建系统是这样的:

Foo foo = new Foo(); 
Bar bar = new Bar(); 
Baz baz = new Baz(); 
foo.setBar(bar); 
bar.setBaz(baz); 
baz.setFoo(foo); 

然后,以使其更加坚固,你可以用更好的异常打造出来如果没有进行必要的协会,则处理。你甚至可以使用工厂方法来创建这些对象(如上所述),以帮助确保它们不会被错误地创建。

+1

我最终只在Baz上使用了依赖的setter,但事实证明这似乎足够了。我宁愿编译时检查,但运行时检查是我猜的下一个最好的事情。感谢您的建议。 – user1582024

相关问题