torikatsu.dev

Flutterとかプログラミングとかガジェットとか書きます

Dartのコンストラクタ紹介2

こんにちは、とりかつです。

今回は、前回の記事で紹介しきれなかったファクトリコンストラクタについて紹介したいと思います。

ファクトリコンストラク

Dartにはgenerative constructor, constant constructorの他にfactory constructorというものがあります。

factoryコンストラクタはコンストラクタ内でインスタンスを生成しません。なので、自分でインスタンスを生成する必要があります。

コンストラクタ内でインスタンスを生成しない特性を生かし、シングルトンパターンで使われたりします。

以下のスニペットのように宣言します。

class Sample {
  factory Sample() {
    _instance ??= Sample._();
    return _instance;
  }

  Sample._();

  static Sample _instance;
}

このスニペットでは、_instancenullのとき、プライベートなネームドコンストラクタを呼び出して_instanceに代入することでシングルトンパターンを実現しています。

ですが、こんな書き方をせずとも、以下のように実装することもできそうです。

class Sample {
  Sample._();

  static Sample _intance;

  static Sample getInstance() {
    _instance ??= Sample._();
    return _instance;
  }
}

コードの振る舞いは変わりませんが、コードの印象は大きく変わります。

factoryを使った時

final sample = Sample();

従来のシングルトンパターン

final sample = Smaple.getInstance();

考えは様々ですが、使い手にシングルトンパターンを意識させたいなら従来のシングルトンパターンを使い、使い手にシングルトンであることを意識させたくないならfactoryを使うと混乱を避けらると思いました。


少し話は変わりますが、インスタンスの生成方法を隠蔽する実装もできそうです。(むしろこっちがファクトリコンストラクタの本命だとおもってる)

class Sample {
    factory Sample(SampleType type) {
      switch () {
        case SampleType.A:
          Sample._a();
          return;
        case SampleType.B:
          Sample._b();
          return;
      }
    }

    Sample._a() {
      /// todo somthing
    }

    Sample._b() {
      /// todo somthing
    }
}

enum SampleType {
  A,
  B,
}

おわりに

ファクトリコンストラクタを使わなくても実装できてしまうケースがほとんどだと思うので、ファクトリコンストラクタは使いどころが難しいと私は感じました。ですがこれを使いこなすことでよりDartライクなコードになるとおもうので、積極的に使っていきましょう。