单例模式确保只创建一个类的一个实例。我如何在Dart中构建它?
感谢Dart的factory constructors,很容易建立一个单身人士:
class Singleton {
static final Singleton _singleton = new Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
你可以用new
构建它
main() {
var s1 = new Singleton();
var s2 = new Singleton();
print(identical(s1, s2)); // true
print(s1 == s2); // true
}
由于我不是非常喜欢使用new
关键字或其他构造函数,例如调用单例,我更喜欢使用名为inst
的静态getter,例如:
// the singleton class
class Dao {
// singleton boilerplate
Dao._internal() {}
static final Dao _singleton = new Dao._internal();
static get inst => _singleton;
// business logic
void greet() => print("Hello from singleton");
}
示例用法:
Dao.inst.greet(); // call a method
// Dao x = new Dao(); // compiler error: Method not found: 'Dao'
// verify that there only exists one and only one instance
assert(identical(Dao.inst, Dao.inst));
您好,这样的事情怎么样?非常简单的实现,Injector本身是单例,并且还在其中添加了类。当然可以很容易地扩展。如果您正在寻找更复杂的东西,请查看此包装:https://pub.dartlang.org/packages/flutter_simple_dependency_injection
void main() {
Injector injector = Injector();
injector.add(() => Person('Filip'));
injector.add(() => City('New York'));
Person person = injector.get<Person>();
City city = injector.get<City>();
print(person.name);
print(city.name);
}
class Person {
String name;
Person(this.name);
}
class City {
String name;
City(this.name);
}
typedef T CreateInstanceFn<T>();
class Injector {
static final Injector _singleton = Injector._internal();
final _factories = Map<String, dynamic>();
factory Injector() {
return _singleton;
}
Injector._internal();
String _generateKey<T>(T type) {
return '${type.toString()}_instance';
}
void add<T>(CreateInstanceFn<T> createInstance) {
final typeKey = _generateKey(T);
_factories[typeKey] = createInstance();
}
T get<T>() {
final typeKey = _generateKey(T);
T instance = _factories[typeKey];
if (instance == null) {
print('Cannot find instance for type $typeKey');
}
return instance;
}
}
单例实例后无法更改对象的单例
class User {
final int age;
final String name;
User({
this.name,
this.age
});
static User _instance;
static User getInstance({name, age}) {
if(_instance == null) {
_instance = User(name: name, idade: age);
return _instance;
}
return _instance;
}
}
print(User.getInstance(name: "baidu", age: 24).age); //24
print(User.getInstance(name: "baidu 2").name); // is not changed //baidu
print(User.getInstance()); // {name: "baidu": age 24}
以下是在Dart中创建单例的几种不同方法的比较。
class SingletonOne {
SingletonOne._privateConstructor();
static final SingletonOne _instance = SingletonOne._privateConstructor();
factory SingletonOne(){
return _instance;
}
}
class SingletonTwo {
SingletonTwo._privateConstructor();
static final SingletonTwo _instance = SingletonTwo._privateConstructor();
static SingletonTwo get instance { return _instance;}
}
class SingletonThree {
SingletonThree._privateConstructor();
static final SingletonThree instance = SingletonThree._privateConstructor();
}
上面的单例实例化如下:
SingletonOne one = SingletonOne();
SingletonTwo two = SingletonTwo.instance;
SingletonThree three = SingletonThree.instance;
注意:
我最初问这是一个question,但发现上述所有方法都是有效的,选择在很大程度上取决于个人偏好。
我发现阅读new Singleton()
并不是非常直观。您必须阅读文档才能知道new
实际上并没有像通常那样创建新实例。
这是做单身人士的另一种方式(基本上是安德鲁所说的)。
LIB / thing.dart
library thing;
final Thing thing = new Thing._private();
class Thing {
Thing._private() { print('#2'); }
foo() {
print('#3');
}
}
main.dart
import 'package:thing/thing.dart';
main() {
print('#1');
thing.foo();
}
请注意,由于Dart的延迟初始化,直到第一次调用getter时才会创建单例。
如果你愿意,你也可以在单例类上实现单例作为静态getter。即Thing.singleton
,而不是顶级的吸气剂。
还阅读了Bob Nystrom对singletons from his Game programming patterns book的看法。
如何在库中使用全局变量呢?
single.dart
:
library singleton;
var Singleton = new Impl();
class Impl {
int i;
}
main.dart
:
import 'single.dart';
void main() {
var a = Singleton;
var b = Singleton;
a.i = 2;
print(b.i);
}
或者这不赞成?
单例模式在Java中是必要的,其中全局变量的概念不存在,但似乎你不需要在Dart中走很长的路。
由const构造函数和工厂执行dart singleton
class Singleton {
factory Singleton() =>
const Singleton._internal_();
const Singleton._internal_();
}
void main() {
print(new Singleton() == new Singleton());
print(identical(new Singleton() , new Singleton()));
}
这是另一种可能的方式:
void main() {
var s1 = Singleton.instance;
s1.somedata = 123;
var s2 = Singleton.instance;
print(s2.somedata); // 123
print(identical(s1, s2)); // true
print(s1 == s2); // true
//var s3 = new Singleton(); //produces a warning re missing default constructor and breaks on execution
}
class Singleton {
static final Singleton _singleton = new Singleton._internal();
Singleton._internal();
static Singleton get instance => _singleton;
var somedata;
}
修改@Seth Ladd回答谁更喜欢像.shared
这样的Swift风格的单身人士:
class Auth {
// singleton
static final Auth _singleton = Auth._internal();
factory Auth() => _singleton;
Auth._internal();
static Auth get shared => _singleton;
// variables
String username;
String password;
}
样品:
Auth.shared.username = 'abc';
这是一个结合其他解决方案的简洁示例。访问单例可以通过以下方式完成:
singleton
全局变量。Singleton.instance
模式。注意:您应该只实现三个选项中的一个,以便使用单例的代码是一致的。
Singleton get singleton => Singleton.instance;
ComplexSingleton get complexSingleton => ComplexSingleton._instance;
class Singleton {
static final Singleton instance = Singleton._private();
Singleton._private();
factory Singleton() => instance;
}
class ComplexSingleton {
static ComplexSingleton _instance;
static ComplexSingleton get instance => _instance;
static void init(arg) => _instance ??= ComplexSingleton._init(arg);
final property;
ComplexSingleton._init(this.property);
factory ComplexSingleton() => _instance;
}
如果需要进行复杂的初始化,那么在程序中稍后使用该实例之前,您必须这样做。
例
void main() {
print(identical(singleton, Singleton.instance)); // true
print(identical(singleton, Singleton())); // true
print(complexSingleton == null); // true
ComplexSingleton.init(0);
print(complexSingleton == null); // false
print(identical(complexSingleton, ComplexSingleton())); // true
}
这应该工作。
class GlobalStore {
static GlobalStore _instance;
static GlobalStore get instance {
if(_instance == null)
_instance = new GlobalStore()._();
return _instance;
}
_(){
}
factory GlobalStore()=> instance;
}