-
-
Save theburningmonk/6401183 to your computer and use it in GitHub Desktop.
class MyClass { | |
static final MyClass _singleton = new MyClass._internal(); | |
factory MyClass() { | |
return _singleton; | |
} | |
MyClass._internal() { | |
... // initialization logic here | |
} | |
... // rest of the class | |
} | |
// consuming code | |
MyClass myObj = new MyClass(); // get back the singleton | |
... | |
// another piece of consuming code | |
MyClass myObj = new MyClass(); // still getting back the singleton |
I actually came up with something like this:
import 'dart:async';
import 'package:rxdart/rxdart.dart';
import 'package:example/app_config.dart';
class ApplicationConfigurationService {
static final ApplicationConfigurationService _instance =
ApplicationConfigurationService._singelton();
static final _behaviorSubject = BehaviorSubject<AppConfig>();
final StreamSink<AppConfig> configStreamSink = _behaviorSubject.sink;
final Stream<AppConfig> configStream = _behaviorSubject.stream;
factory ApplicationConfigurationService() => _instance;
ApplicationConfigurationService._singelton();
}
I am writing a command-line program and in the main.dart I'am writing on the StreamSink of my AppConfigService after parsing my JSON file. Due the service is using a BehaviorSubject the last value will be cached and replayed to new subscribers / listeners.
Later when I need the config values I do the following:
final applicationConfigurationService = ApplicationConfigurationService();
...
applicationConfigurationService.configStream.first.then((config) {
_appConfig = config;
});
Or if you want you can even react to config changes when you need that feature.
I think, one could use the static instance variable also.
MyClass myObj1 = MyClass._singleton; // get back the singleton
This feels like an antipattern, singleton should be implemented with a private constructor and a static singleton class.
Having a constructor that returns the singleton on behind hides this detail from the developer.
The pattern proposed by @theburningmonk actually has a problem.
I just spent twenty minutes chasing down a bug which this pattern obscured.
The problem was that my _internal method was throwing an exception.
In the exception handler I was trying to reference the same factory instance. This caused an npe as _singleton was null (due to the _internal exception) so I got an npe rather than the original exception.
The following pattern avoids this issue:
class MyClass {
static MyClass _singleton;
factory MyClass() => _singleton ??= MyClass._internal();
MyClass._internal() {
... // initialization logic here
}
... // rest of the class
}
The only disadvantage is that _singleton can no longer be final.
Singleton design pattern is intended to create one and only one (single) instance of a class.
If you wanted a single instance with a parameter, how would you do that?
Do you see any issue in this code?
class MyClass {
MyClass._(this.parameter);
final String parameter;
static MyClass? _instance;
static void initialize(String parameter) {
_instance = MyClass._(parameter );
}
static MyClass get instance => _instance!; // throw an "initialize first" error
// access parameter
}
Singleton design pattern is intended to create one and only one (single) instance of a class.
If you wanted a single instance with a parameter, how would you do that?
Do you see any issue in this code?
This is not a singleton implementation.
See this for reference: Dart Null-Safty Singleton with parameters
Can MyClass extend an abstract class with non-null constructor? If so how?
@ascmp Trying to solve exactly the same problem with AppConfig as a singleton using params from relevant json files.
Have you found any elegant solutions?..