Comparing ways to create singletons in Dart - dart

I read these posts:
How do you build a Singleton in Dart?
How to implement Singleton pattern in Dart using factory constructors?
Object Structures in Dart
I'm having a little trouble understanding the difference between the following ways of creating singletons:
1. Factory constructor
class SingletonOne {
SingletonOne._privateConstructor();
static final SingletonOne _instance = SingletonOne._privateConstructor();
factory SingletonOne(){
return _instance;
}
}
2. Static field with getter
class SingletonTwo {
SingletonTwo._privateConstructor();
static final SingletonTwo _instance = SingletonTwo._privateConstructor();
static SingletonTwo get instance { return _instance;}
}
3. Static field
class SingletonThree {
SingletonThree._privateConstructor();
static final SingletonThree instance = SingletonThree._privateConstructor();
}
These are instantiated like this:
SingletonOne one = SingletonOne();
SingletonTwo two = SingletonTwo.instance;
SingletonThree three = SingletonThree.instance;
Questions
Günter Zöchbauer said about this question:
There is no need to use the factory constructor. The factory
constructor was convenient when new was not yet optional because then
it new MyClass() worked for classes where the constructor returned a
new instance every time or where the class returned a cached instance.
It was not the callers responsibility to know how and when the object
was actually created.
I don't understand how new being optional now makes the factory constructor unnecessary now. Before you couldn't do something like SingletonTwo or SingletonThree above?
Günter Zöchbauer also said:
You can also change static final DbHelper _db = new
DbHelper._constr(); to static final DbHelper singleton = new
DbHelper._constr(); and remove the singleton getter I suggested in my
answer. It depends on your use case. You might not be able to use a
field initializer if you need additional config values to create the
instance. In your example it would be sufficient though.
What are the use cases for each of the singleton patterns above (SingletonOne, SingletonTwo, and SingletonThree)? It would be helpful to see an example for each. Wouldn't the factory pattern be useful if you wanted to hide the fact that the class was a singleton (as described here)?

As Günter Zöchbauer stated in the comments, each of the three ways you listed of creating singletons are the same. Use your personal preference to choose one.
I'm going to add some additional notes:
SingletonOne when instantiated looks like any other class. So you could use this one if you want to hide the fact that it is a singleton (and leave the option to make it not be a singleton in the future). You could also pass in arguments in the constructor.
SingletonTwo would allow you to do other work before returning the instance.
SingletonThree is the shortest, and short clean code is desirable in my book, all other things being equal.

Since Dart allows root-level variables, a perfectly good, lazy loading Singleton can be had thusly:
final store = _Store();
class _Store {
//
}
Limitations
Like your three other examples, this won't work if you need asynchronous construction. Also, like SingletonTwo and SingletonThree you can't pass in any arguments from the calling scope.
For a singleton that needs async construction and arguments I would use something like this:
class StoreService {
static StoreService? _instance;
StoreService._() {}
static Future<StoreService> instance() async {
// we can await things here
if (_instance == null) {
_instance = StoreService._();
}
return _instance!;
}
}

Related

How can I require that a class has fromJson in Dart? [duplicate]

Say I have the abstract class A
abstract class A {
A.someConstructor(Foo foo);
}
and all subclasses of A should then implement such constructor:
class B extends A {
#override
B.someConstructor(Foo foo) {
// ...
}
}
So basically what I want is some kind of abstract constructors.
Is there any way of achieving this (of course the above code does not work) or do I need a normal abstract method which then creates the object and sets its properties?
EDIT: Ok so it looks like the only way to create at least a similar behaviour would be something like this:
abstract class A {
A.someConstructor(Object foo);
}
class B extends A {
B.someConstructor(Object foo) : super.someConstructor(foo) {
// ...
}
}
This isn't exactly useful, and after some thinking about my problem I realized that in fact my original goal itself is not really neccessary, so this questions is now answered.
You want to enforce a pattern on the constructors of subclasses. The Dart language has no support for doing that.
Dart has types and interfaces which can be used to restrict values and class instance members.
If a class implements an interface, then its instance members must satisfy the signatures declared by the super-interface. This restricts instance members.
If a variable has a type, for example a function type, then you can only assign values of that type to it. This restricts values. Because a class is a subtype of its interfaces, the subclass restriction means that class typed variables can be used safely (the subtype can be used as its supertype because it has a compatible interface).
There is no way to restrict static members or constructors of classes, or members of libraries, because there is no way to abstract over them. You always have to refer directly to them by their precise name, so there is no need for them to match a particular pattern.
(Which may explain why you found the goal not necessary too).
In this situation, your subclasses must call the A.someConstructor constructor, but they are free to choose the signature of their own constructors. They can do:
class B extends A {
B.someConstructor(Object foo) : super.someConstructor(foo);
}
// or
class C extends A {
C.differentName(Object foo) : super.someConstructor(foo);
}
// or even
class D extends A {
D() : super.someConstructor(new Object());
}
Constructors aren’t inherited
Subclasses don’t inherit constructors from their superclass. A
subclass that declares no constructors has only the default (no
argument, no name) constructor.
Source

Why must the _internal() be called in the class?

Even though I am familiar with singleton, Dart's factory is confusing. I have seen an existing question, but the only thing I got from the answer is that the name can be whatever identifier that starts with an _. Even though the person had asked why it should be called, the answer does not seem to be explaining that.
If I comment out the Dog._internal(); line, I get Method not found: 'Dog._internal'. It looks like calling a method, but is it like C's function prototype? But it has no return type. Can someone explain the Dog._internal(); line to me?
class Dog
{
static final Dog dog = Dog._internal();
//Dog._internal();
factory Dog()
{
return dog;
}
}
There are multiple concepts going on so lets go through the example:
factory Dog()
{
return dog;
}
This defines a factory constructor. Factory constructors are much like normal static methods but must always return an object which are compatible with the type of which the factory constructor is part of. In our example the factory constructor must return a Dog object.
It is not a constructor in that sense that we already have created a object when we enter this method. Again, it can be compared to static Dog Dog() but is allowed to override the default constructor. So we must create the object manually and return it.
This allows us to control the behavior of when objects are created and in our case allows us to have a singleton pattern so when somebody are trying to create an instance of Dog they will always get the same object.
Dog._internal();
This is called a named constructor. Constructors in Dart can have given names which makes it easier to distinguish different constructors. But also because Dart does not allows us to override methods with different number of parameters.
Also, because of the name starting with _ it means this constructor is marked private and cannot be used outside of the library it is part of. So if your code is part of a library, the code importing your library are not allowed to call your private constructor.
This is again a nifty trick to allow us to make a singleton since we don't want other than our own code to create a new instance (which are the only instance we want to create).
static final Dog dog = Dog._internal();
This is essential creating the singleton. The reason for this is that static variables in Dart are lazy-evaluated so the value dog does not really have any value before it is called. After first call, the value are "cached" so Dog._internal(7) are only called once as long our application (or more specific, our isoleate instance) are running.
I would properly call the variable _instance or _dog so it is also private.
Dog.foo(); defines a named constructor named foo that takes no arguments and has no body. It's equivalent to Dog.foo() {}. Similarly, Dog._internal(); defines a named constructor named _internal. This would be more obvious if the constructor took arguments and did work, for example:
class Dog {
static final Dog dog = Dog._internal(7);
Dog._internal(this.years) {
registerAnimal(this);
}
factory Dog() {
return dog;
}
int years;
}

How to implement a general class for singleton?

I've been trying to implement a state management project for my design patterns course. I have implemented the singleton because I know that's essential for keeping state of a class. What I would like to do is: Create a general class, so that others could use it in their projects. How do I do that? My code so far:
class StateManager{
static final StateManager _instance = StateManager._singleton();
StateManager._singleton();
factory StateManager(){
return _instance;
}
}
My other solution to try and make it general:
class AppProvider extends StateManager<AppProvider>{
int i = 10;
String data = "adas";
}
class StateManager<T extends AppProvider>{
static final StateManager _instance = StateManager._singleton();
StateManager._singleton();
factory StateManager(){
return _instance;
}
}
I want the AppProvider class to be the client class, and I want the StateManager to automatically handle the fact that AppProvider should be a singleton, and maintain the state of AppProvider.. I really don't know how to do that.
Forcing a class to be a singleton through inheritance alone is not going to work. That's not something that the language supports. Constructors are not inherited, neither are static members, and you need those to access the singleton.
In order to be able to create an instance of a class at all, the class needs a generative constructor.
That generative constructor will create a new instance every time it's invoked, because that's what generative constructors do.
For a subclass to be able to extend a class, the superclass must have an accessible generative constructor too, but at least the superclass can be made abstract.
In order to force a class to be a singleton (if you really want that, because a singleton is really something of an anti-pattern; it makes the class act like it's just a bunch of global variables, and that makes testing harder), each such class needs to have a public static way to access or create the instance, and a private generative constructor.
So, basically, your first approach does what is needed, and since the constructors are not inherited, you need to do that for every singleton class, and there is nothing useful to inherit.
So, there is nothing you can do with inheritance to make singleton-ness be inherited, and you can't even help because everything a singleton needs is static.
A different approach is to make the state classes entirely private, so you don't have to worry about someone else creating instances, and give them a constant generative constructor each, and then only refer to them using const _ThisState() or const _ThatState().
This puts the responsibility on the user (you!) to only create one instance of each state object, but it also gives a very easy way to do that, because const _ThisState() will provide the same instance every time.
Or use the enum pattern, and have:
abstract class State {
static const State thisState = const _ThisState();
static const State thatState = const _ThatState();
const State._();
void handle(Context context, Object argument);
}
class _ThisState implements State {
const _ThisState();
void handle(Context context, Object argument) { ... }
}
class _ThatState implements State {
const _ThatState();
void handle(Context context, Object argument) { ... }
}
and then just refer to the state instances as State.thisState. I find that more readable than creating instances of seemingly unrelated classes.

Is it possible to initialize a library?

I am trying out the new Dart FFI in making wrappers for libsodium. Libsodium needs to be initialized with calling init(). But I don't think the user should be burdened to remember this and I also wouldn't like to check some global state variable.
I know that Go has package init() functions which run when a package gets included. Is there something similar in Dart?
Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.
Of course I could just wrap everything up into a class and run init() in the constructor but there isn't much sense in instatiating a class which basically only exposes static methods. Besides, I would like to preserve the procedural style of libsodium.
You could have a singleton instance and expose library functions as methods on the instance, and you could provide a public getter function that automatically does initialization.
For example, something like:
Libsodium? _instance;
Libsodium get libsodium => _instance ??= Libsodium._();
class Libsodium {
Libsodium._() {
// Do initialization.
}
void foo() {
// ...
}
void bar() {
// ...
}
}
and then callers would need to use it via:
import 'libsodium.dart';
libsodium.foo();
This would hide the class instantiation and wouldn't look any different to callers than if you were to use only top-level functions with a namespace (import 'libsodium.dart' as libsodium).
Dart does not have any way to implicitly run code. No code runs before main, and all code running after main does so because it was invoked directly or indirectly from the main method. So, no.
If you need something initialized, there is a number of options.
You can use a lazily initialized static variable:
var _initialState = _init();
int doSomething(arguments) {
_initialState;
do the something.
}
The reading of _initialState will ensure that init is invoked the first time
it's needed, and not after that. You can even store things in the state for
later use.
The singleton implementation object suggested by #jamesdlin. It basically does the
same thing, then puts the methods on the object instead of being static.
Another variant is to do exactly that, but with a private instance, and have the
public top-level functions forward to the singleton object. Then you get the
procedural API and still ensures that the state object is initialized.
(This may be better for testing, allowing you to have multiple state objects alive
at the same time).
Require people to call init.

When should final fields, factory constructors or private fields with getters be used in dart?

If you can figure out how to rename this question, I'm open for suggestions.
In the Dart language, one can write a class with final fields. These are fields that can only be set before the constructor body runs. That can be on declaration (usually for static constants inside a class), in an initialiser list syntax when declaring the constructor or using the this.field shorthand:
class NumBox{
final num value;
NumBox(this.value);
}
Let's say I actually needed to do some processing on instance creation and can't just initialise the field before the constructor. I can switch to using a private non-final field with a getter:
class NumBox{
num _value;
NumBox(num v) {
_value = someComplexOperation(v);
}
num get value => _value;
}
Or I can get a similar behavior using a factory constructor:
class NumBox{
final num value;
factory NumBox(num v) {
return new NumBox._internal(someComplexOperation(v));
};
NumBox._internal(this.value);
}
I hit a similar bump when I tried learning Dart a few years back and now that I have more baggage, I still don't know. What's the smarter way to do this?
A factory constructor is a good way, it allows to pre-calculate without limitations any values that you then pass to a normal constructor to forward to final fields.
An alternative way is initializer list which is executed before the constructor body and therefore allows to initializer final fields:
class NumBox{
final num value;
NumBox(num v) : value = someComplexOperation(v)
}
In the initializer list you are not allowed to read this because the instance isn't fully initialized yet.
DartPad example
You should design your API with your user in mind, then implement it in whatever way is simpler and more maintainable to you. This question is about the latter part.
Making fields final is great when it's possible, and when it isn't, making them private with a public getter is a good alternative. It's your choice what to do, because it's you who is going to maintain your class, nobody else should need to look behind the public API.
If you need a complex computation, Günther Zöchbauer's suggestion is the first to turn to: Use a helper function. In some cases, you can even do it inline
class MyThing {
final x;
MyThing(args) : x = (() { complex code on args; return result;} ());
}
It gets ugly quickly, though, so having it as a static helper function is usually better.
If your complex computation doesn't match this, which ususally means that there is more than one field being initialized with related values, then you need a place to store an intermediate value and use it more than once when initializing the object.
A factory constructor is the easy approach, you can compute everything you need and then call the private generative constructore at the end. The only "problem" is that by not exposing a generative constructor, you prevent other people from extending your class. I quoted "problem" because that's not necessarily a bad thing - allowing people to extend the class is a contract which puts restrictions on what you can do with the class.
I tend to favor public factory constructors with private generative constructors even when it's not needed for any practical reason, just to disable class extension.
class MyClass {
const factory MyClass(args) = MyClass._; // Can be const, if you want it.
const MyClass._(args) : ... init .. args ...;
}
If you need a generative constructor, you can use a forwarding generative constructor to introduce an intermediate variable with the computed value:
class MyClass {
final This x;
final That y;
MyClass(args) : this._(args, _complexComputation(args));
MyClass._(args, extra) : x = extra.theThis, y = extra.theThat, ...;
}
All in all, there is no strict rule. If you prefer final fields, you can do extra work to make them final, or you can just hide the mutability behind a getter - it's an implementation and maintainability choice, and you're the one maintaining the code.
As long as you keep the abstraction clean, and keeps track of what you have promised users (generative constructor? const constructor?) so you won't break that, you can change the implementation at any time.

Resources