Implementation

We will use the Singleton design pattern to save our Singleton example’s state in the Flutter Design Patterns application. To make it more straightforward, the state saves only a single text property. Example’s state itself is implemented in three different ways:

Using a Singleton design pattern which is implemented by definition;

Using a Singleton design pattern which is implemented using the Dart language capabilities;

Without using a Singleton at all.

ExampleStateBase

Since the example’s state is implemented in several different ways, its abstraction was created in order to reuse it in all of the implementations. Hence, class ExampleStateBase provides this abstracted state:

As already mentioned, the example’s state consists only of a single String property stateText and its initial value initialText. Properties stateText ant initialText are marked as protected — it is needed to make these properties accessible only for those classes which extend the ExampleStateBase class. However, Dart does not support the protected visibility in the same way as some of you could expect it to be coming from the other OOP language’s background such as C# or Java — we can only annotate these properties as protected but it is more as a reminder for the developer not to use them from outside of the class scope (Visual Studio Code editor even shows a warning in this case). Also, ExampleStateBase provides methods to operate the stateText.

Singleton’s implementation by definition

In the class diagram below, concrete classes of the Flutter Design Patterns application are represented which implement the Singleton design pattern by definition.

Class Diagram — Implementation of the Singleton design pattern

ExampleStateByDefinition extends the ExampleStateBase class to obtain access to the state (in this case, stateText and initialText) and its methods.

ExampleStateByDefinition implements the Singleton design pattern and handles the instance creation. The instance is only accessible through the static method getState().

Code of the ExampleStateByDefinition:

Singleton’s implementation using Dart magic

Class ExampleState implements a Singleton design pattern “the Dart way”:

By comparing this code with the previous implementation, you could notice that the static method getState() is missing — well, it is just not needed anymore! Dart language provides a factory constructor. It is used to implement a constructor that does not always create a new instance of its class — it is a nice and elegant way to implement the class as a Singleton, isn’t it? Now you can create the instance of ExampleState class by calling its factory constructor in the same manner as you would do that by calling a default one — factory constructor will create a new instance or return the existing one if it was already initiated.

ExampleStateWithoutSingleton

Just a simple implementation of the state class without bothering it with Singleton or any other ”fancy-schmancy” design patterns.

Example

First of all, a markdown file is prepared and provided as a pattern’s description:

The example itself uses all three different implementations of the state:

Singleton implementations (ExampleStateByDefinition and ExampleState) create a new state object only on the first creation of the SingletonExample widget, but the ExampleStateWithoutSingleton instance is created on each creation of the SingletonExample widget. This behaviour could be noticed by changing the state and forcing the example’s widget to rebuild e.g. by switching tabs:

Or by navigating to the main menu and back:

As you can see, the state which is implemented as a Singleton remains the same since a new instance of the state class is not created on example’s widget rebuild.

All of the code changes for the Singleton design pattern and its example implementation could be found here.