多くのコンストラクタやオプションパラメーターが必要なクラスを作成するときにBuilderというデザインパターンがあります。
私はEffective Javaで紹介されているパターンを利用しています。
非常に美しくクラスが作れる素晴らしいパターンですね。
さて、で、Builderパターンで作成したクラスのサブクラスをどうするの?
という疑問がありまして、下記に答えがありましたが、日本語情報があまりなかったので、書いておきます。
http://stackoverflow.com/questions/17164375/subclassing-a-java-builder-class
Offer(オファー)というクラスがあり、そのサブクラスでDone(成約)というものがあります。
まずは、Offerで利用するビルダーでジェネリクスを利用するように変更します。
public class Offer {
private final String offer_id;
private final int offer_price;
protected final ArrayList<Delivery> delivery_list;
private final int bid_number;
private final int more_number;
private final MatchRate match_rate;
private final boolean is_bid;
private final boolean is_more;
private final boolean is_matched;
private final String winner_id;
private final String status;
private final boolean is_approved; //成約しているかどうか
private final String bidder_id;
protected final int max_weight;
protected final int number_of_delivery;
protected final int number_of_sender;
protected final int take_over;
protected final boolean is_pack;
protected final int company_id;
protected final String company_name;
protected final double company_review;
protected final int pack_id;
protected final Pack pack;
public static class Builder<T extends Builder> {
//必須パラメーター
private final String offer_id;
private final int offer_price;
private final ArrayList<Delivery> delivery_list;
//オプションパラメーター 初期値を設定
private int bid_number = 0;
private int more_number = 0;
private MatchRate match_rate = MatchRate.NOT_GOOD;
private boolean is_bid = false;
private boolean is_more = false;
private boolean is_matched = false;
private String winner_id;
private String status;
private boolean is_approved;
private String done_id;
private String bidder_id = null;
private int max_weight;
private int number_of_delivery = 0;
private int number_of_sender = 0;
private int take_over = 0;
private boolean is_pack = false;
private int company_id;
private String company_name;
private double company_review;
private int pack_id;
private Pack pack;
/**
* @param offer_id
* @param offer_price
* @param delivery_list
*/
public Builder(String offer_id, int offer_price, ArrayList<Delivery> delivery_list) {
this.offer_id = offer_id;
this.offer_price = offer_price;
this.delivery_list = delivery_list;
}
public T bid_number(int val) {
bid_number = val;
return (T)this;
}
public T more_number(int val) {
more_number = val;
return (T)this;
}
public T match_rate(MatchRate val) {
match_rate = val;
return (T)this;
}
public T is_bid(boolean val) {
is_bid = val;
return (T)this;
}
public T is_more(boolean val) {
is_more = val;
return (T)this;
}
public T is_matched(boolean val) {
is_matched = val;
return (T)this;
}
public T status(String val) {
status = val;
return (T)this;
}
public T winner_id(String val) {
winner_id = val;
if (winner_id != null) {
is_matched = true;
}
return (T)this;
}
public T is_approved(boolean val) {
is_approved = val;
return (T)this;
}
public T done_id(String val) {
done_id = val;
return (T)this;
}
public T bidder_id(String val) {
bidder_id = val;
return (T)this;
}
public T max_weight(int val) {
max_weight = val;
return (T)this;
}
public T number_of_delivery(int val) {
number_of_delivery = val;
return (T)this;
}
public T number_of_sender(int val) {
number_of_sender = val;
return (T)this;
}
public T take_over(int val) {
take_over = val;
return (T)this;
}
public T is_pack(boolean val) {
is_pack = val;
return (T)this;
}
public T company_id(int val) {
company_id = val;
return (T)this;
}
public T company_name(String val) {
company_name = val;
return (T)this;
}
public T company_review(double val){
company_review = val;
return (T)this;
}
public T pack_id(int val) {
pack_id = val;
return (T)this;
}
public T pack(Pack val) {
pack = val;
return (T)this;
}
public Offer build() {
return new Offer(this);
}
}
protected Offer(Builder builder) {
offer_id = builder.offer_id;
offer_price = builder.offer_price;
delivery_list = builder.delivery_list;
bid_number = builder.bid_number;
more_number = builder.more_number;
match_rate = builder.match_rate;
is_bid = builder.is_bid;
is_more = builder.is_more;
is_matched = builder.is_matched;
is_approved = builder.is_approved;
bidder_id = builder.bidder_id;
status = builder.status;
winner_id = builder.winner_id;
max_weight = builder.max_weight;
number_of_delivery = builder.number_of_delivery;
number_of_sender = builder.number_of_sender;
take_over = builder.take_over;
is_pack = builder.is_pack;
company_id = builder.company_id;
company_name = builder.company_name;
company_review = builder.company_review;
pack_id = builder.pack_id;
pack = builder.pack;
}
public String getOfferId() {
return offer_id;
}
public int getOfferPrice() {
return offer_price;
}
// 後は省略
}
Doneクラスは次のようにします。
public class Done extends Offer{
private final String done_id;
private final boolean is_canceled;
public static class Builder extends Offer.Builder<Builder> {
//必須パラメーター
private String done_id;
private boolean is_canceled;
/**
* @param offer_id
* @param offer_price
* @param delivery_list
*/
public Builder(String offer_id, int offer_price, ArrayList<Delivery> delivery_list) {
super(offer_id, offer_price, delivery_list);
}
public Builder Done(String done_id, boolean is_canceled) {
this.done_id = done_id;
this.is_canceled = is_canceled;
return this;
}
public Done build() {
return new Done(this);
}
}
protected Done(Builder builder) {
super(builder);
done_id = builder.done_id;
is_canceled = builder.is_canceled;
}
public String getDone_id(){
return done_id;
}
}
いやー、こういうことを考える、頭の良い人がいるもんですね!!
パチパチパチパチ![[smile]](https://i0.wp.com/oc-technote.com/wp-content/themes/oc/assets/images/face/smile.png?w=525&ssl=1)
Doneをインスタンスにする場合は、次のようにnewします。
Done done = new Done.Builder(offer_id, offer_price, delivery_list)
.winner_id(winner_id)
.number_of_delivery(receiver_number)
.number_of_sender(sender_number)
.max_weight(max_weight)
.take_over(take_over)
.is_pack(is_pack)
.pack_id(getPackId(data, context))
.pack(pack)
.Done(done_id, false)
.build();
