Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何避免将上下文传递给一组方法调用?_Java_Design Patterns - Fatal编程技术网

Java 如何避免将上下文传递给一组方法调用?

Java 如何避免将上下文传递给一组方法调用?,java,design-patterns,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) { th

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

我还尝试使用依赖项注入使代码可测试:

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 wan不依赖于Foo,你可以做如下事情:

Foo foo = new Foo(new Bar(new Baz()));
Baz可以接受任何Foo,因此如果它只得到顶部的一个Foo就没有问题,从而形成一个循环

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

以可测试的方式将Foo导入Baz的最干净的方法是什么

Foo
参数添加到
doBaz()
是我唯一的选择吗?(这意味着Foo需要将“this”传递给doBar,然后doBar再传递给doBaz,等等……或者有更好的方法吗?)

编辑:

也许问题描述确实有用

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

但是,代码中可能存在不一致性(想想未声明的方法)。导致这个问题的原因是,与大多数编译器不同,这个编译器不应该简单地向用户抛出一堆错误,而是为用户提供了输入更多代码的选项

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

如果在用户提供的代码中有更多不明确之处,它将再次允许用户澄清

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

一些其他选项:

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

  • 您可以维护对“previous”对象的引用,并使用它从Baz向后遍历:

    福班{

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

    分类栏{ 富富,; 巴兹巴兹

    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类{ 酒吧; 富富,

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

  • 其他一些选择:

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

  • 您可以维护对“previous”对象的引用,并使用它从Baz向后遍历:

    福班{

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

    分类栏{ 富富,; 巴兹巴兹

    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类{ 酒吧; 富富,

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


  • 您可以分别构造这些对象,然后相互注册

    最简单的形式如下所示:

    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);
    
    然后,像这样构建系统:

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

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

    您可以分别构建这些对象,然后相互注册

    最简单的形式如下所示:

    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);
    
    然后,像这样构建系统:

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

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

    如果您更详细地描述实际问题,可能会有所帮助。很可能有一种不同的分解,周期性更小。好的,完成了。只是流程本身是以用户可见的方式递归的,因此可能很难摆脱递归算法本身。我有一种模糊的感觉,在这里,访问者可能是更好的方法。如果您更详细地描述实际问题,可能会有所帮助。很可能有一种不同的分解,周期性更小。好的,完成了。只是流程本身是以用户可见的方式递归的,所以可能很难摆脱递归算法本身。我有一种模糊的感觉,在这里,访问者可能是更好的方法。我最终使用了setter来实现对Baz的依赖,但这似乎足够了。我更喜欢编译时检查,但我想运行时检查是次好的选择。谢谢你的建议。我最后只在Baz上使用了setter作为依赖项,但事实证明这似乎已经足够了。我更喜欢编译时检查,但我想运行时检查是次好的选择。谢谢你的建议。