すらぼうの開発ノート

モバイルアプリエンジニアのメモ

【Flutter / Dart】Singleton(シングルトン)パターンの実装

本エントリではデザインパターンの一つである「Singleton」をFlutterアプリで実装する方法を説明する。



Singletonパターンとは

あるクラスのインスタンスが一つだけ生成されること。

インスタンスが一つだけしか存在しないため、インスタンスが管理する変数などへのアクセス経路も管理しやすい。

使用ケース

Singletonは以下のようなケースで使用されることが多い。

  • クラスのサイズが大きいケース
  • 設定情報やログ情報など、情報を単一にまとめることに意味のあるケース

使用する際の注意

ただしSingletonはアンチパターンと考えられる場合もあるので、利用する際には注意してほしい。

stackoverflow.com

アンチパターンとして扱われている理由としては例えば「インスタンスが一つなので、モックのインスタンスが作成できずunit testがやりにくい」、といった点が挙げられる。


Flutterアプリでの実装例

例としてアプリケーション上の画面の設定情報をSingletonクラスで作成する。

仮の設定項目としては

  • 言語(日本語or英語)
  • ダークモード(有効or無効)
  • 文字サイズ(10 ~ 30の整数)

があるものとする。

コード

作成したクラスは以下。

ポイント

Singletonクラスを実装する上でのポイントは以下。

  • factoryキーワードをコンストラクタの前に記述する
  • _internal()コンストラクタを用意する(名称はなんでも良い)
  • クラス内で生成するインスタンスはprivateにする

以下で順に説明する。

factoryキーワードをコンストラクタの前に記述する

factoryキーワードを使用することでコンストラクタが呼ばれた際に既存のインスタンスを返却している。

なので一度SettingInfoインスタンスが生成されると、以降の呼び出しでは既存のインスタンスが返却されるようになるので、結果として何度コンストラクタを呼ばれてもアプリケーション内でインスタンスを一つにすることができる。

factoryキーワードについて

factoryキーワードは必ずしもコンストラクタが呼ばれた際に毎回新しいインスタンスを返すわけではない場合に使用する。このキーワードがコンストラクタの前に記載されていない場合、コンストラクタで値をreturnすることはできない。

dart.dev

_internal()コンストラクタを用意する

クラス内で使用する名前付きコンストラクタを用意する。分かりやすく_internal()命名することが多い。 このコンストラクタはprivateにするため先頭にアンダーバーを記述する。

クラス内で生成するクラスはprivateにする

クラス外からのインスタンス取得は全てfactoryコンストラクタを経由させたいので、クラス内に生成したインスタンスはprivateにする必要がある。 そこでインスタンス名の先頭にアンダーバーを記述する。