Reputation: 817
Given a util class with two similar methods that differs only in the field setter/getter:
public static void method_A(Dbo dbo) {
if (dbo instanceof Zdbo) {
((Zdbo)dbo)
.getSome()
.forEach(z -> z.setFieldX(dbo.getFieldX()));
}
}
public static void method_B(Dbo dbo) {
if (dbo instanceof Zdbo) {
((Zdbo)dbo)
.getSome()
.forEach(z -> z.setFieldZ(dbo.getFieldZ()));
}
}
my question is: how can I rid of the duplicate code?
My approach was to achieve something like this:
private static void xxx(Dbo dbo, Consumer c) {
if (dbo instanceof Zdbo) {
((Zdbo)dbo).getSome().forEach(c);
}
}
Upvotes: 2
Views: 91
Reputation: 34470
I would use a Function<Dbo, T>
to extract the field and a BiConsumer<Some, T>
to set the field to each Some
object:
private static <T> void setField(
Dbo dbo,
Function<? super Dbo, ? extends T> extractor,
BiConsumer<? super Some, ? super T> setter) {
Consumer<Some> c = some -> setter.accept(some, extractor.apply(dbo));
if (dbo instanceof Zdbo) ((Zdbo) dbo).getSome().forEach(c);
}
This adapts the BiConsumer<Some, T> setter
to a Consumer<Some> c
, by binding the 2nd argument of setter
to the value returned by the extractor
function.
Then, you can invoke it as follows:
public static void method_A(Dbo dbo) {
setField(dbo, Some::getFieldX, Some::setFieldX);
}
public static void method_B(Dbo dbo) {
setField(dbo, Some::getFieldY, Some::setFieldY);
}
Upvotes: 0
Reputation: 109593
public static Stream<Zdbo> getSome(Dbo dbo) {
return dbo instanceof Zdbo ? ((Zdbo)dbo).getSome() : Stream.empty();
}
public static Optional<Zdbo> asZdbo(Dbo dbo) {
return dbo instanceof Zdbo ? Optional.of((Zdbo)dbo) : Optional.empty();
}
public static void method_A(Dbo dbo) {
getSome(dbo).forEach(z -> z.setFieldX(dbo.getFieldX()));
}
public static void method_B(Dbo dbo) {
getSome(dbo).forEach(z -> z.setFieldZ(dbo.getFieldZ()));
}
I would keep it on the Stream or Optional level. method_A and method_B above can simply be replaced by their content, without the need of passing a setter and getter. Also it is more versatile, and does not generate the code overhead.
Notice that for instanceof+cast a next java might have a better solution.
Upvotes: 2