Webアプリ開発をしているとよく、画面プレゼンテーション層と
サービスロジック層の間の為にコンバータなるものを作らされたりして
面倒なものです。
よく書かされてしまう、getter で持ってきて、setter に食わせる
a.setPhonNumber(b.getPhoneNumber());
みたいなものを大量に書かされて、まあコンパクトに書けないことはないんですけど、
単純に左から右へ渡すのでなく、加工などの処置が必要で
生成済インスタンスの状態毎に処置が必要な時は、面倒くさいものです。
先日の、new 演算子で生成する変数のコーディングを減らす方法 - Oboe吹きプログラマの黙示録
に触発されて、
名称はさておき、以下を考えました。。。
getterとして、Function<T, R> で取得して、setter として BiConsumer を実行します。
import java.util.function.BiConsumer;
import java.util.function.Function;
@FunctionalInterface
public interface ApplyBiConsumer<T, U>{
void accept(T t, U u);
static <T, U, V> ApplyBiConsumer<T, U> of(Function<T, V> f, BiConsumer<U, V> c) {
return (t,u)->{
c.accept(u, f.apply(t));
};
}
}
使用サンプルは以下のとおりです。
import lombok.Data;
@Data
public class Foo{
private String name;
private int id;
private LocalDate birthday;
}
import lombok.Data;
@Data
public class Person{
private String name;
private int id;
private LocalDate birthday;
private String info;
}
Foo foo;
Person person;
TODO
ApplyBiConsumer.of(Foo::getName, Person::setName).accept(foo, person);
ApplyBiConsumer.of(Foo::getId, Person::setId).accept(foo, person);
ApplyBiConsumer.of(Foo::getBirthday, Person::setBirthday).accept(foo, person);
ApplyBiConsumer.of(e->((Foo)e).getDay().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))
, Item::setInfo).accept(foo, person);
ApplyBiConsumer.of(Foo::getDay, (t, u)->{
((Person)t).setInfo(((LocalDate)u).format(DateTimeFormatter.ofPattern("yyyy年MM月dd日")));
}).accept(foo, person);
a.setPhonNumber(b.getPhoneNumber()); の記述形式の方が短いと言えますが、
ラムダ式で書けるということは、変換式をsetter である BiConsumer の実行まで待てるので、
以下のように、この ApplyBiConsumer をリストに溜めてから実行できます。
List<ApplyBiConsumer<Foo, Person>> alist = Arrays.asList(
ApplyBiConsumer.of(Foo::getName, Person::setName),
ApplyBiConsumer.of(Foo::getId, Person::setId),
ApplyBiConsumer.of(Foo::getBirthday, Person::setBirthday)
);
を用意しておけば、(Java11なら、List.of() で書くと思います。)
alist.stream().forEach(e->e.accept(foo, person));
のように、いつでもセットを実行できるわけです。
でも、この ApplyBiConsumer は、以下のように、BiConsumer を継承したものとして、
定義した方が良いのかもしれません。
継承なら、 void accept(T t, U u); を以下のとおりここでは書かないです。
import java.util.function.BiConsumer;
import java.util.function.Function;
@FunctionalInterface
public interface ApplyBiConsumer<T, U> extends BiConsumer<T, U>{
static <T, U, V> ApplyBiConsumer<T, U> of(Function<T, V> f, BiConsumer<U, V> b) {
return (t,u)->{
b.accept(u, f.apply(t));
};
}
}
最終的には、後日投稿の以下がベスト
Functionの結果をBiConsumerで実行する(3) - Oboe吹きプログラマの黙示録