1. ホーム
  2. java

ビルダーパターンと多数の必須パラメータ

2023-09-03 10:41:27

質問

現在までに、私は に続く の実装を使用しています。 ここで ):

public class Widget {
    public static class Builder {
        public Builder(String name, double price) { ... }
        public Widget build() { ... }
        public Builder manufacturer(String value) { ... }
        public Builder serialNumber(String value) { ... }
        public Builder model(String value) { ... }
    }

    private Widget(Builder builder) { ... }
}

これは、私が遭遇した、さまざまな必須/必須およびオプションのパラメータを持つ複雑なオブジェクトを構築する必要があるほとんどの状況でうまく機能します。しかし、私は最近、すべてのパラメーターが必須である場合 (または少なくとも大部分が必須である場合) に、このパターンがどのような利益をもたらすかを理解するのに苦労しています。

これを回避する 1 つの方法は、渡されるパラメータを独自のクラスに論理的にグループ化し、ビルダー コンストラクターに渡されるパラメータの数を減らすことでした。

例えば、代わりに

Widget example = new Widget.Builder(req1, req2, req3,req4,req5,req6,req7,req8)
                           .addOptional(opt9)
                           .build();

は以下のようにグループ化されます。

Object1 group1 = new Object1(req1, req2, req3, req4);
Object2 group2 = new Object2(req5, req6);

Widget example2 = new Widget.Builder(group1, group2, req7, req8)
                            .addOptional(opt9)
                            .build();

別々のオブジェクトを持つことで物事はかなり単純化されますが、コードに慣れていない人には少し難しくもなります。私が考えたことのひとつは、すべてのパラメータを独自の addParam(param) メソッドに移し、必要なパラメータの検証を build() メソッドで必要なパラメータの検証を行います。

ベストプラクティスとは何でしょうか、また、私が考慮しなかったより良いアプローチがあるのでしょうか。

どのように解決するのですか?

しかし、私は最近、すべてのパラメータが必須である場合 (または少なくとも大多数が必須である場合)、このパターンがどのような利点があるのかを理解するのに苦労しています。

流暢なビルダーパターンはまだ有益です。

  1. より読みやすい - 名前のついたパラメータを効果的に使用できるので、呼び出しが無名の引数の長いリストになることはありません。

  2. 順不同 - これは、単一のビルダーセッター呼び出しの一部として、または単に、この特定のインスタンス化の最も意味をなすビルダーセッターメソッドを呼び出すための自然な順序を使用させることによって、論理グループにまとめて引数をグループ化することができます。


Widget example = new Widget.Builder(req1, req2, req3,req4,req5,req6,req7,req8)
                               .addOptional(opt9)
                               .build();

は以下のようにグループ化されます。

Object1 group1  = new Object1(req1, req2, req3, req4);
Object2 group2  = new Object2(req5, req6);
Widget example2 = new Widget.Builder(group1, group2, req7, req8)
                            .addOptional(opt9)
                            .build();

別々のオブジェクトを持つことで物事はかなり単純化されますが、コードに慣れていない人には少し難しくもなります。私が考えたことのひとつは、すべてのパラメータを独自の addParam(param) メソッドに移し、必要なパラメータの検証を build() メソッドで必要なパラメータの検証を行います。

私は、適切な場合や自然な場合には、ハイブリッドに賛成します。 すべてコンストラクタにある必要はありません。 または である必要はなく、それぞれのパラメータに独自のaddParamメソッドがあります。 Builderでは、どちらか一方、またはその中間、あるいは複合的な処理を柔軟に行うことができます。

Widget.Builder builder = new Widget.Builder(Widget.BUTTON);

builder.withWidgetBackingService(url, resource, id);
builder.withWidgetStyle(bgColor, lineWidth, fontStyle);
builder.withMouseover("Not required");

Widget example = builder.build();