如何重构仅在 java 中调用对象的方法不同的方法?
How to refactor methods that only differ in which method they call on an object in java?
可能是个初学者问题,但我卡在了我的盒子里。
假设界面如下:
public interface Foo {
void one() throws Exception;
void two() throws Exception;
}
还有这个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
}
}
}
现在如果 oneOnAllFoos
和 twoOnAllFoos
除了 foo one()
和 two()
调用之外是相同的,我如何重构 MyClass
到获得一个包含所有逻辑的方法,让我指定要调用 Foo
对象上的哪个方法?我知道可以使用反射,但我认为也必须有一种 KISS 方式。谢谢!
编辑: 添加了 throws Exception
接口方法。
Edit2: // assuming more code...
包含接口方法调用的异常处理。我在那里收集抛出的异常,然后将它们作为复合异常进一步抛出(必须首先处理所有 Foo
。
您可以在此处使用Consumer界面:
private forEachFoo(Consumer<Foo> consumer) {
for each foo: consumer.accept(foo) ...
然后使用简单的 lambda 传递不同的消费者,例如:
public void oneOnAllFoos() {
forEachFoo(f -> f.one());
或者,按照其他答案中的建议,使用方法参考 Foo::one
。
编辑:当您的方法抛出已检查的异常时,您可以使用自己的 Consumer/Function 接口执行两个操作,请参阅 here 了解详细信息。
你需要传入一个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.
}
}
可通过
调用
onAllFoos(Foo::one);
我觉得处理你的问题的最好方法(至少在 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);
}
}
}
选择使用 consumer
只是因为您的方法 one()
和 two()
没有返回任何东西。
可能是个初学者问题,但我卡在了我的盒子里。
假设界面如下:
public interface Foo {
void one() throws Exception;
void two() throws Exception;
}
还有这个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
}
}
}
现在如果 oneOnAllFoos
和 twoOnAllFoos
除了 foo one()
和 two()
调用之外是相同的,我如何重构 MyClass
到获得一个包含所有逻辑的方法,让我指定要调用 Foo
对象上的哪个方法?我知道可以使用反射,但我认为也必须有一种 KISS 方式。谢谢!
编辑: 添加了 throws Exception
接口方法。
Edit2: // assuming more code...
包含接口方法调用的异常处理。我在那里收集抛出的异常,然后将它们作为复合异常进一步抛出(必须首先处理所有 Foo
。
您可以在此处使用Consumer界面:
private forEachFoo(Consumer<Foo> consumer) {
for each foo: consumer.accept(foo) ...
然后使用简单的 lambda 传递不同的消费者,例如:
public void oneOnAllFoos() {
forEachFoo(f -> f.one());
或者,按照其他答案中的建议,使用方法参考 Foo::one
。
编辑:当您的方法抛出已检查的异常时,您可以使用自己的 Consumer/Function 接口执行两个操作,请参阅 here 了解详细信息。
你需要传入一个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.
}
}
可通过
调用onAllFoos(Foo::one);
我觉得处理你的问题的最好方法(至少在 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);
}
}
}
选择使用 consumer
只是因为您的方法 one()
和 two()
没有返回任何东西。