Dartのfactoryコンストラクタ、またはシングルトンについてのまとめ

Dartのクラスでシングルトンを作成したい時がある。

その時はfactoryコンストラクタを使うとシンプルに実装できるので紹介していく。

factoryコンストラクタとは?

factoryコンストラクタとは、コンストラクタ時にどのインスタンスを返すかを決めることができる特別なコンストラクタのことを言う。

この機能により、シングルトンパターンを楽に実装できるようになる。

まずはコードを見てみよう。

class Logger {
  static Logger? _instance;

  // privateコンストラクタ
  Logger._();

  // factoryコンストラクタ
  factory Logger() {
    _instance ??= Logger._();
    return _instance!;
  }
}

// 使用例
void main() {
    var logger1 = Logger();
    var logger2 = Logger();
    print(logger1 == logger2); // true(同じインスタンス)
}

Loggerがfactoryコンストラクタを使って実装されている。 中身を一行ずつ見ていく。

シングルトンで扱うインスタンスをstaticプロパティで管理する。

class Logger {
  static Logger? _instance;

プライベートでしかコンストラクタすることができないようにする。 なので、クラスの外側(main関数とか)からは初期化することができない。

Logger._();

factoryコンストラクタを定義する。_instanceが未定義であれば、 コンストラクタを実行する。最終的に_instanceを返す。

  // factoryコンストラクタ
  factory Logger() {
    _instance ??= Logger._();
    return _instance!;
  }

最初は面食らうかもしれないが、慣れるとなんてことはない。

また、factoryコンストラクタ部分は、アロー関数を使えば以下のように一行で表現することができる。

factory Logger() => _instance ??= Logger._();

つまり、先程のLoggerクラスは以下のように書き直せる。

class Logger {
  static Logger? _instance;
  Logger._();
  factory Logger() => _instance ??= Logger._();
}

// 使用例
void main() {
    var logger1 = Logger();
    var logger2 = Logger();
    print(logger1 == logger2); // true(同じインスタンス)
}

随分とシンプルに表現できた。これでシングルトンパターンを実装するのが簡単になった。