如何避免在一堆方法调用中传递上下文?

时间:2016-12-30 18:15:52

标签: java design-patterns

假设我有一个问题,直觉上最好使用递归来解决。

我也尝试使用依赖注入来使代码可以测试:

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...
        }
    }
}

现在,如果Baz不依赖于Foo,你可以做类似的事情:

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

Baz可以接受任何Foo,所以如果只是将它放在顶部就没问题,从而形成一个循环。

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

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

Foo添加doBaz()参数是我的唯一选择吗? (暗示Foo需要将“this”传递给doBar,然后将其传递给doBaz等等......还是有更好的方法?)

修改

也许问题描述确实有用。

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

但是,代码中可能存在不清楚(想想未申报的方法)。导致这个问题的原因在于,与大多数编译器不同,这个编译器不应该只是在用户处呕吐一堆错误,而是为用户提供输入更多代码的选项。

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

如果在用户提供的此代码中有更多不清楚的内容,则会再次允许用户澄清。

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

2 个答案:

答案 0 :(得分:0)

其他一些选择:

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

  2. 您可以维护对“previous”对象的引用,并使用Baz中的对象进行遍历:

    class Foo {

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

    }

    class Bar {     Foo 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();
    }
    

    }

    班级Baz {     酒吧吧;     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...
        }
    }
    

    }

答案 1 :(得分:0)

您可以单独构造这些对象,然后彼此注册。

最简单的形式如下:

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);

然后,为了使其更加健壮,如果尚未建立必要的关联,您可以通过更好的异常处理来构建它。您甚至可以使用工厂方法一起创建这些对象(如上所述),以帮助确保它们不会被错误地创建。