[英]How to refactor methods that only differ in which method they call on an object in java?
Probably kind of a beginner question but I am stuck in my box.可能是一个初学者问题,但我被困在我的盒子里。
Assuming the following interface:假设有以下界面:
public interface Foo {
void one() throws Exception;
void two() throws Exception;
}
And this class:而这个类:
class MyClass {
private Collection<Foo> foos;
MyClass(Collection<Foo> foos) {
this.foos = foos;
}
public void oneOnAllFoos() {
// assuming more code...
for (Foo foo : foos) {
// assuming more code...
foo.one(); // the only different line
}
}
public void twoOnAllFoos() {
// assuming more code...
for (Foo foo : foos) {
// assuming more code...
foo.two(); // the only different line
}
}
}
Now in case the oneOnAllFoos
and twoOnAllFoos
are the same except for the foo one()
and two()
calls, how can I refactor MyClass
to get one method containing all logic letting me specify which method on the Foo
objects to be called?现在,如果
oneOnAllFoos
和twoOnAllFoos
除了 foo one()
和two()
调用之外相同,我如何重构MyClass
以获得一个包含所有逻辑的方法,让我指定要调用Foo
对象的哪个方法? I know it is possible using reflection but I think there must be a KISS way, too.我知道使用反射是可能的,但我认为也必须有一种KISS方式。 Thanks!
谢谢!
Edit: added throws Exception
to the interface methods.编辑:添加
throws Exception
到接口方法。
Edit2: the // assuming more code...
contains the exception handling of the interface method calls. Edit2:
// assuming more code...
包含接口方法调用的异常处理。 There I collect the thrown exceptions to then throw them further as composite exception (must process all Foo
s first.我在那里收集抛出的异常,然后将它们作为复合异常进一步抛出(必须首先处理所有
Foo
。
You need to pass in a ThrowingConsumer<Foo>
:您需要传入一个
ThrowingConsumer<Foo>
:
interface ThrowingConsumer<T> {
void accept(T t) throws Exception; // signature very similar to a normal Consumer
}
public void onAllFoos(ThrowingConsumer<Foo> consumer) {
// assuming more code...
for (Foo foo : foos) {
// assuming more code...
consumer.accept(foo); // handle exception here.
}
}
Callable via可通过
onAllFoos(Foo::one);
You can use the Consumer interface here:您可以在此处使用消费者界面:
private forEachFoo(Consumer<Foo> consumer) {
for each foo: consumer.accept(foo) ...
to then pass in different consumers with simple lambdas, like:然后使用简单的 lambda 传递给不同的消费者,例如:
public void oneOnAllFoos() {
forEachFoo(f -> f.one());
or, as suggested in the other answer, by using a method reference Foo::one
.或者,如另一个答案中所建议的,通过使用方法引用
Foo::one
。
Edit: when your methods throw checked exceptions, you can do two use your own Consumer/Function interface see here for details.编辑:当您的方法抛出已检查的异常时,您可以使用自己的消费者/功能接口执行两次操作,请参阅此处了解详细信息。
I feel that the best way to deal with your problem (in Java 8 at least) is to create a private method that takes a Consumer<Foo>
as a parameter, such as:我觉得处理您的问题的最佳方法(至少在 Java 8 中)是创建一个将
Consumer<Foo>
作为参数的私有方法,例如:
class MyClass {
private Collection<Foo> foos;
MyClass(Collection<Foo> foos) {
this.foos = foos;
}
public void oneOnAllFoos() {
abstractOnAllFoos(Foo::one);
}
public void twoOnAllFoos() {
abstractOnAllFoos(Foo::two);
}
private void abstractOnAllFoos(Consumer<Foo> fooConsumer) {
// assuming more code...
for (Foo foo : foos) {
// assuming more code...
fooConsumer.accept(foo);
}
}
}
The choice of using a consumer
has been made only because your methods one()
and two()
aren't returning anything.选择使用
consumer
只是因为你的方法one()
和two()
没有返回任何东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.