Dart – implementing the Singleton pattern with factory constructors

In Dart there is an interesting language feature called ‘Factory Constructors’, which effectively allows you to override the default behaviour when using the new keyword – instead of always creating a new instance the factory constructor is merely required to return an instance of the class, the difference is important.

Factory constructors allow you to implement a number of techniques and patterns without altering code that consumes your class. For instance,

  • Singleton pattern which we will look at more closely.
  • Object pooling, a useful technique for reducing the amount of allocations (and its associated allocation cost and consequent GC pressure) in performance critical applications.
  • Flyweight pattern which is already discussed in more detail in this Idiomatic Dart article.

These are just 3 use cases that I can think of off the top of my head, please feel free to suggest any more that I have missed.

Problems with common Singleton pattern implementations

In other languages (well, the ones that I’m familiar with anyway!), in order to implement the Singleton pattern you have to ensure that the class’s constructor is not exposed publicly and that access to the singleton instance is done via a static Singleton property. Revered C#/Java developer Jon Skeet has a very good article on the various solutions one might adopt to implement the singleton pattern in C#.

Inflexible

These implementations require code that consumes your class to be aware of its implementation of the singleton pattern and create a vast blast radius throughout your application should you one day decide that the singleton pattern is no longer necessary/applicable.

For instance, if assumptions in your application change drastically (and they often do..) and you need to switch to the flyweight or another pattern instead to cater for changing requirements and/or assumptions.

Unintentional tight coupling

In the case of C# (where static members are not allowed on interfaces and abstract classes are un-constructible) the standard singleton pattern also create tight coupling to a concrete implementation where it’s seldom necessary.

You can, to some degree, work around this issue of tight coupling by introducing an IOC container as middle man between your class and its consumers, most IOC containers provide some mechanism for controlling object lifespans (transient, singleton, pooled, etc.). However, you now have tight coupling to the IOC container instead…

Singleton pattern with Factory constructors

You can implement the singleton pattern using factory constructors like this:

the key thing here is that any consuming code is completely oblivious to the fact that we have just implemented the singleton pattern. If we were to continue our mind later or forced to adopt a different pattern because of changing requirement, there will be trivial or no change on all the consuming code!

Links

Idiomatic Dart – Factory constructors

Jon Skeet – Implementing the Singleton pattern in C#

Liked this article? Support me on Patreon and get direct help from me via a private Slack channel or 1-2-1 mentoring.
Subscribe to my newsletter


Hi, I’m Yan. I’m an AWS Serverless Hero and the author of Production-Ready Serverless.

I specialise in rapidly transitioning teams to serverless and building production-ready services on AWS.

Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.

Hire me.


Check out my new course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. Including basic concepts, HTTP and event triggers, activities, callbacks, nested workflows, design patterns and best practices.

Get Your Copy