factoryについて調べていて「シングルトン」というワードがよく出てきたので、深掘りたいと思いまとめみました。Flutterを日常で実装してて、時々出てくるシングルトンという考え方について理解を深めたい方や改めてどんなものだったか知りたい方の参考になれば幸いです。
シングルトンとは
シングルトンとは、「インスタンスをアプリ全体で一つだけグローバルに管理するデザインパターン」のことです。
特徴
- グローバルなアクセス・変更
- 必要なデータや機能にグローバルにアクセスでき変更も用意
- メモリの使用量削減
- 単一のインスタンスを保持しているだけなので、パフォーマンスの向上、メモリの節約が容易に
- DB接続などサイズが大きいインスタンス生成に向いている
- データの管理を一つにまとめる
- ログや設定情報を一つにまとめて有効なケースに有効
デメリット
- グローバルに管理するので、複雑になるケースもあり
- ユニットテストがやりにくい
- インスタンスが一つのためモックが作れない
ソースコードサンプル
ポイント
- factoryを使う
- 普通のコンストラクタは新しいインスタンスを作成してしまう
_internalのような内部用のコンストラクタを用意
class MySingleton {
// ① インスタンスを静的に保持
static final MySingleton _instance = MySingleton._internal();
// ② 外部からは factory で同じインスタンスを返す
factory MySingleton() {
return _instance;
}
// ③ プライベートな内部用コンストラクタ
MySingleton._internal();
// ④ フィールドやメソッドを自由に追加
int counter = 0;
void increment() {
counter++;
}
}_を使って内部用のコンストラクタにして、外部からインスタンスを作れないようにしている。 MySingletonではなく、 _internal()という内部用コンストラクタにすることで通常のnewではインスタンスを作れない。
MySingleton._internal();staticで静的にすることで唯一のインスタンスを作っている。
「唯一」であることがシングルトンパターンにおいて重要。
static final MySingleton _instance = MySingleton._internal();factoryを使うことで、既存のインスタンスを返すことが可能になる。
返す値としては、_instanceとクラスで唯一宣言したインスタンスを返すことでシングルトンを再現。
factory MySingleton() {
return _instance;
}■使い方
void main() {
var s1 = MySingleton();
var s2 = MySingleton();
s1.increment();
print(s2.counter); // → 1(同じインスタンスを共有している)
}s1 と s2 は別の変数だが、中身のインスタンスは同じ。
factroyコンストラクタについて下記記事を参考にしてみてください。
シングルトンの使用にあたって注意すること
アンチパターンの議論

上記記事だと
- シングルトンは便利だが、問題を生みやすく、過剰に使われてきた。
- 必要なときだけ慎重に使うべきパターン。
- 使う前に「テスト性」「再利用性」「並列動作」「依存関係」を必ず考えるべき。
とのことです。
必ずしも「シングルトンを使う」と決めるのではなく、下記のような使うべき場面のみで使用することが大切です。
- 「データベース接続を1つに制限したい」
- 「リソースが厳しいので複数作られると困る」
このように 本当に唯一性が必要なケース では有効。
シングルトン以外の選択
RiverpodやProviderなど便利な状態管理ツールが出てきたので、そちらを使って状態管理する方が安全でテストしやすい。使うタイミングは慎重にプロジェクトごとで要検討かなと思います。
最後に
簡単にシングルトンについて説明してきました。シングルトンはデザインパターンなので概念は他の言語でも活かせるかなと思います。理解を深めぜひFlutterライフ、モバイル開発ライフをエンジョイしてください。
ではまた。




コメント