Builderパターンについて調べたのでFlutterでサンプルを作ってみた

# Builderパターンについて軽く

あるクラスのコンストラクタで設定する変数の数が多く、
けど、全部必須ではない場合、
必須ではない変数の設定パターンによって、コンスラクタの数が膨大になってしまう。
また、コンストラクタでは必須の変数のみ設定し、
後からセッターで他の変数を設定するという場合でも、
呼び出すセッター文が膨大になってしまい、呼び出し元でのオブジェクト生成箇所が長くなってしまう。

これを回避するために、
決まった値でのオブジェクト生成部分を手順化したクラスを別で用意し、対象オブジェクトを生成するというパターン。

この手順が記載されたクラスを `Director` と呼び、
Director が作成するクラスを `Builder` と呼ぶ。

このパターンを使う時、　`Director`　は手順のみ記載し、
`Builder` のサブクラスなどに流用できるように、
必須パラメータであってもセッターで設定するようにし、固定のクラスのコンストラクタではない形にした方が良さそう。

また、 `Director` は決まった値での手順になるので、
値が流動的な時は、このパターンは使いづらいのかもしれない。

# サンプルとして何を作ったか

「☆3出力」ボタン
と
「♪3出力」ボタン
を押すとそれぞれ対象の文字が表示される。

表示する文字数の設定を
`Director` と `Builder` で定義する。

# クラス図

```mermaid
classDiagram
  class DecorationBuilder {
    <<abstract>>
    +set characterNum()
    +output()
  }
  class DecorationStar {
    +set characterNum()
    +output()
  }
  class DecorationMusicNote {
    +set characterNum()
    +output()
  }
  class Director {
    +construct()
  }
  class MyApp {
  }
  class MyHomePage {
  }
  class _MyHomePageState {
  }

  DecorationBuilder <|.. DecorationStar
  DecorationBuilder <|.. DecorationMusicNote

  DecorationBuilder <-- Director

  MyHomePage <-- MyApp
  _MyHomePageState <-- MyHomePage
  DecorationStar <-- _MyHomePageState
  DecorationMusicNote <-- _MyHomePageState
  Director <-- _MyHomePageState
```

# コード

[GitHub](https://github.com/kenta4327/flutter_builder) に完全版があります。

```dart:decoration_builder.dart
abstract class DecorationBuilder {
  set characterNum(int characterNum);
  String output();
}
```

```dart:decoration_star.dart
import 'package:flutter_builder/utils/decoration_builder.dart';

class DecorationStar implements DecorationBuilder {
  final _character = '☆';
  int? _characterNum;

  @override
  set characterNum(int characterNum) {
    _characterNum = characterNum;
  }

  @override
  String output() {
    String outputString = '';
    for (var i = 0; i < _characterNum!; i++) {
      outputString = '$outputString$_character';
    }
    return outputString;
  }
}
```

```dart:decoration_music_note.dart
import 'package:flutter_builder/utils/decoration_builder.dart';

class DecorationMusicNote implements DecorationBuilder {
  final _character = '♪';
  int? _characterNum;

  @override
  set characterNum(int characterNum) {
    _characterNum = characterNum;
  }

  @override
  String output() {
    String outputString = '';
    for (var i = 0; i < _characterNum!; i++) {
      outputString = '$outputString$_character';
    }
    return outputString;
  }
}
```

```dart:director.dart
import 'package:flutter_builder/utils/decoration_builder.dart';

class Director {
  DecorationBuilder? _decorationBuilder;

  Director(DecorationBuilder decorationBuilder) {
    _decorationBuilder = decorationBuilder;
  }

  void construct() {
    _decorationBuilder?.characterNum = 3;
  }
}
```

```dart:main.dart
  :
  : // 割愛
  :
class _MyHomePageState extends State<MyHomePage> {
  final _textController = TextEditingController();
  String _outputText = '';
  DecorationBuilder? _decorationStar;
  DecorationBuilder? _decorationMusicNote;

  @override
  void initState() {
    super.initState();

    _decorationStar = DecorationStar();
    Director director = Director(_decorationStar!);
    director.construct();

    _decorationMusicNote = DecorationMusicNote();
    director = Director(_decorationMusicNote!);
    director.construct();
  }
  :
  : // 割愛
  :
```

以上