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
中有一个静态方法返回这样的实例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
中有一个静态方法返回这样的实例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作为依赖项,但事实证明这似乎已经足够了。我更喜欢编译时检查,但我想运行时检查是次好的选择。谢谢你的建议。