Set*_*add 219
感谢Dart的工厂构造函数,构建单例很容易:
class Singleton {
static final Singleton _singleton = Singleton._internal();
factory Singleton() {
return _singleton;
}
Singleton._internal();
}
Run Code Online (Sandbox Code Playgroud)
你可以用它来构建它 new
main() {
var s1 = Singleton();
var s2 = Singleton();
print(identical(s1, s2)); // true
print(s1 == s2); // true
}
Run Code Online (Sandbox Code Playgroud)
Sur*_*gch 66
这是在Dart中创建单例的几种不同方式的比较。
class SingletonOne {
SingletonOne._privateConstructor();
static final SingletonOne _instance = SingletonOne._privateConstructor();
factory SingletonOne(){
return _instance;
}
}
Run Code Online (Sandbox Code Playgroud)
class SingletonTwo {
SingletonTwo._privateConstructor();
static final SingletonTwo _instance = SingletonTwo._privateConstructor();
static SingletonTwo get instance { return _instance;}
}
Run Code Online (Sandbox Code Playgroud)
class SingletonThree {
SingletonThree._privateConstructor();
static final SingletonThree instance = SingletonThree._privateConstructor();
}
Run Code Online (Sandbox Code Playgroud)
上面的单例是这样实例化的:
SingletonOne one = SingletonOne();
SingletonTwo two = SingletonTwo.instance;
SingletonThree three = SingletonThree.instance;
Run Code Online (Sandbox Code Playgroud)
注意:
我最初将其作为一个问题,但发现上述所有方法均有效,并且选择很大程度上取决于个人喜好。
Gre*_*owe 34
我发现阅读新的Singleton()并不是非常直观.您必须阅读文档才能知道new实际上并没有像通常那样创建新实例.
这是做单身人士的另一种方式(基本上是安德鲁所说的).
LIB/thing.dart
library thing;
final Thing thing = new Thing._private();
class Thing {
Thing._private() { print('#2'); }
foo() {
print('#3');
}
}
Run Code Online (Sandbox Code Playgroud)
main.dart
import 'package:thing/thing.dart';
main() {
print('#1');
thing.foo();
}
Run Code Online (Sandbox Code Playgroud)
请注意,由于Dart的延迟初始化,直到第一次调用getter时才会创建单例.
如果你愿意,你也可以在单例类上实现单例作为静态getter.即Thing.Singleton,而不是顶级的getter.
还阅读了Bob Nystrom 从他的游戏编程模式书中对单身人士的看法.
Ham*_*med 22
这是一个简单的答案:
首先,我们需要一个private和static类类型的属性。
其次,构造函数应该是private,因为我们要防止从类外部初始化对象。
最后,我们检查实例的可空性,如果它为空,我们将实例化并返回它,否则我们将返回已经实例化的实例。
延迟加载的实现
class Singleton {
static Singleton? _instance;
Singleton._();
static Singleton get instance => _instance ??= Singleton._();
...
}
Run Code Online (Sandbox Code Playgroud)
使用 Eager Loading 实现
class Singleton {
static Singleton _instance = Singleton._();
Singleton._();
static Singleton get instance => _instance;
...
}
Run Code Online (Sandbox Code Playgroud)
用法
Singleton.instance.someMethod();
Run Code Online (Sandbox Code Playgroud)
小智 12
如何在库中使用全局变量呢?
single.dart:
library singleton;
var Singleton = new Impl();
class Impl {
int i;
}
Run Code Online (Sandbox Code Playgroud)
main.dart:
import 'single.dart';
void main() {
var a = Singleton;
var b = Singleton;
a.i = 2;
print(b.i);
}
Run Code Online (Sandbox Code Playgroud)
或者这不赞成?
单例模式在Java中是必要的,其中全局变量的概念不存在,但似乎你不需要在Dart中走很长的路.
小智 9
由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()));
}
Run Code Online (Sandbox Code Playgroud)
这是另一种可能的方式:
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;
}
Run Code Online (Sandbox Code Playgroud)
这是一个结合了其他解决方案的简洁示例。访问单例可以通过以下方式完成:
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;
}
Run Code Online (Sandbox Code Playgroud)
如果您需要进行复杂的初始化,则只需在稍后在程序中使用实例之前执行此操作即可。
例子
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
}
Run Code Online (Sandbox Code Playgroud)
实例化后不能改变对象的单例
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, age: 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}
Run Code Online (Sandbox Code Playgroud)
这就是我在项目中实现单例的方式
灵感来自 flutter firebase =>FirebaseFirestore.instance.collection('collectionName')
class FooAPI {
foo() {
// some async func to api
}
}
class SingletonService {
FooAPI _fooAPI;
static final SingletonService _instance = SingletonService._internal();
static SingletonService instance = SingletonService();
factory SingletonService() {
return _instance;
}
SingletonService._internal() {
// TODO: add init logic if needed
// FOR EXAMPLE API parameters
}
void foo() async {
await _fooAPI.foo();
}
}
void main(){
SingletonService.instance.foo();
}
Run Code Online (Sandbox Code Playgroud)
class FirebaseLessonRepository implements LessonRepository {
FirebaseLessonRepository._internal();
static final _instance = FirebaseLessonRepository._internal();
static final instance = FirebaseLessonRepository();
factory FirebaseLessonRepository() => _instance;
var lessonsCollection = fb.firestore().collection('lessons');
// ... other code for crud etc ...
}
// then in my widgets
FirebaseLessonRepository.instance.someMethod(someParams);
Run Code Online (Sandbox Code Playgroud)
如果您碰巧使用 Flutter 和providerpackage 进行状态管理,那么创建和使用单例非常简单。
Run Code Online (Sandbox Code Playgroud)void main() { runApp( MultiProvider( providers: [ ChangeNotifierProvider(create: (context) => SomeModel()), Provider(create: (context) => SomeClassToBeUsedAsSingleton()), ], child: MyApp(), ), ); }
Run Code Online (Sandbox Code Playgroud)Widget build(BuildContext context) { var instance = Provider.of<SomeClassToBeUsedAsSingleton>(context); ...
在阅读了所有替代方案后,我想出了这个,这让我想起了“经典的单身人士”:
class AccountService {
static final _instance = AccountService._internal();
AccountService._internal();
static AccountService getInstance() {
return _instance;
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我做了其他一些在想要使用 Singleton 时也是必要的事情。例如:
像这样:
class MySingleton {
static final MySingleton _singleton = MySingleton._internal();
String _valueToBeSet;
String _valueAlreadyInSingleton;
String _passedValueInContructor;
get getValueToBeSet => _valueToBeSet;
get getValueAlreadyInSingleton => _valueAlreadyInSingleton;
get getPassedValueInConstructor => _passedValueInContructor;
void setValue(newValue) {
_valueToBeSet = newValue;
}
factory MySingleton(String passedString) {
_singleton._valueAlreadyInSingleton = "foo";
_singleton._passedValueInContructor = passedString;
return _singleton;
}
MySingleton._internal();
}
Run Code Online (Sandbox Code Playgroud)
MySingleton 的使用:
void main() {
MySingleton mySingleton = MySingleton("passedString");
mySingleton.setValue("setValue");
print(mySingleton.getPassedValueInConstructor);
print(mySingleton.getValueToBeSet);
print(mySingleton.getValueAlreadyInSingleton);
}
Run Code Online (Sandbox Code Playgroud)
Singleton可以使用 null 安全运算符和工厂构造函数更好地创建对象。
class Singleton {
static Singleton? _instance;
Singleton._internal();
factory Singleton() => _instance ??= Singleton._internal();
void someMethod() {
print("someMethod Called");
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
void main() {
Singleton object = Singleton();
object.someMethod(); /// Output: someMethod Called
}
Run Code Online (Sandbox Code Playgroud)
注意: ??是一个 Null 感知运算符,如果左侧值为 null,则返回右侧值,这意味着在我们的示例中_instance ?? Singleton._internal();,Singleton._internal()将在对象被调用时第一次返回,其余的_instance将返回。
修改了@Seth Ladd 回答谁更喜欢 Swift 风格的单身人士,例如.shared:
class Auth {
// singleton
static final Auth _singleton = Auth._internal();
factory Auth() => _singleton;
Auth._internal();
static Auth get shared => _singleton;
// variables
String username;
String password;
}
Run Code Online (Sandbox Code Playgroud)
样本:
Auth.shared.username = 'abc';
Run Code Online (Sandbox Code Playgroud)
小智 5
从Dart 2.13版本开始,使用late关键字很容易。Late关键字允许我们延迟实例化对象。
例如,您可以看到它:
class LazySingletonExample {
LazySingletonExample._() {
print('instance created.');
}
static late final LazySingletonExample instance = LazySingletonExample._();
}
Run Code Online (Sandbox Code Playgroud)
注意:请记住,当您调用惰性
instance字段时,它只会被实例化一次。
小智 5
** Dart Sound 空安全中的 Sigleton 范式**
此代码片段展示了如何在 dart 中实现单例 这通常用于我们每次都必须使用类的相同对象的情况,例如。在数据库事务中。
class MySingleton {
static MySingleton? _instance;
MySingleton._internal();
factory MySingleton() {
if (_instance == null) {
_instance = MySingleton._internal();
}
return _instance!;
}
}
Run Code Online (Sandbox Code Playgroud)
如何在 dart flutter 中创建类的单例实例
class ContactBook {
ContactBook._sharedInstance();
static final ContactBook _shared = ContactBook._sharedInstance();
factory ContactBook() => _shared;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
45779 次 |
| 最近记录: |