Optimal Performance: A Journey into Singleton Design Pattern.

Aryan Bisht
4 min readAug 27, 2023

--

In object orientated programming you must have heard about singleton. I can say that it is one of the most controversial and debatable topics of program. Some program think is one of the best thing a developer can ask for while other say a developer should never use this. It up-to you in which category you are. In what ever category at-least you should know what is singleton and how can we achieve this in dart. In this it’s good to use in specific cases.

  • Some people say you should avoid them at all costs. ❌
  • Others are more pragmatic and use them only in specific cases. 🔍
  • And some use them willy-nilly like there’s no tomorrow. 😅

By the end of this article you will know what is singleton and how you can implement this in dart.

What Is a Singleton?

The singleton pattern is a software design pattern that restricts the instantiation of a class to one “single” instance.

May be you got it from the definition and may not. So let me define it clearly to you (that’s why I am here :-) ).

In other words, the singleton pattern ensures that only one instance of a class is ever created, making it easy to access it as a global variable.

Implementation in dart..

class Singleton {
/// private constructor
Singleton._internal() {
// initialization logic
}

/// the one and only instance of this singleton
static final _instance = Singleton._internal();

factory Singleton() {
return _instance();
}
}

In above code we made the constructor private so that class cannot be instantiated outside the file where it is define. We also defined the instance as private so we are using getter to get the instance we are doing so because we don’t want that some-body change the sole instance of our class by mistake.

And that completes the coding part but the important part is after this, why and how use singleton class in dart. Is it even used in dart or not.

One of the biggest user of singleton is firebase. If you have made any application or website then there are very chance you have used firebase or at-least know about firebase. Firebase plugins in dart use singleton

And the only way to call their methods is with the instance getter:

FirebaseFirestore.instance.doc('path/to/document');
FirebaseFunctions.instance.httpsCallable('createOrder');
FirebaseMessaging.instance.deleteToken();

So you think if google/firebase is using this that means it’s best and we can also use in our project but wait before doing so. Most of the libraries use singleton only to prevent you guys from creating more than one instance in your code. But when writing application code, we should be very careful about how we use them, as they can lead to many problems in our codebase.

Flutter apps have deeply nested widget trees. As a result, singletons make it easy to access the objects we need, from any widget. But singletons have many drawbacks and there are better alternatives that are still easy to use.

Drawbacks

  1. Singletons are hard to test

2. Singletons are Implicit Dependencies

3. Lazy Initialization

4. Thread Safety

Note: In Dart, all global variables are lazy-loaded by default (and this is also true for static class variables). This means that they are only initialized when they are first used. On the other hand, local variables are initialized as soon as they are declared, unless they are declared as late.

Alternatives to Singletons

Use Riverpod Providers : —

Riverpod makes it easy to create providers as global variables:

final authRepositoryProvider = Provider<FirebaseAuthRepository>((ref) {
return FirebaseAuthRepository(FirebaseAuth.instance);
});

And if we have a ref object, we can easily read any provider to get its value:

final authRepository = ref.read(authRepositoryProvider);

As a result, we only need to call FirebaseAuth.instance once in the entire codebase (rather than many times), since we can now get or read its value (using either get_it or Riverpod).

Unlike solutions based on InheritedWidget or the Provider package, Riverpod providers live outside the widget tree. This makes them safe to use at compile-time, without runtime exceptions. For more info on this, read my Essential Guide to Riverpod.

Wrap Up

Singletons make it easy to access dependencies in your code. But they create more problems than they solve. A better alternative is to manage dependencies using battle-tested packages such as riverpod.

Happy Coding..!!

More from Aryan Bisht

You can buy me coffee at :- https://www.buymeacoffee.com/aryanbisht

Level Up Coding And Development Journey

Thanks for being a part of our community! Before you go:

  • 👏 If you find this helpful Clap for the story and follow the author 👉
  • 🔔 Follow us: LinkedIn

--

--