单例模式确保只创建一个类的一个实例。我如何在Dart中构建它?
答案 0 :(得分:165)
感谢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
}
答案 1 :(得分:29)
我发现阅读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的看法。
答案 2 :(得分:18)
这里是在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的身份询问此信息,但发现上述所有方法均有效,并且选择很大程度上取决于个人喜好。
答案 3 :(得分:12)
如何在库中使用全局变量呢?
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中走很长的路。
答案 4 :(得分: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()));
}
答案 5 :(得分:8)
这是另一种可能的方式:
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;
}
答案 6 :(得分:5)
在这个例子中,我做了其他一些在想要使用单例时也需要做的事情。例如:
像这样:
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();
}
MySingleton 的使用:
void main() {
MySingleton mySingleton = MySingleton("passedString");
mySingleton.setValue("setValue");
print(mySingleton.getPassedValueInConstructor);
print(mySingleton.getValueToBeSet);
print(mySingleton.getValueAlreadyInSingleton);
}
答案 7 :(得分:4)
如果您碰巧使用 Flutter 和 provider
包进行状态管理,那么创建和使用单例非常简单。
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => SomeModel()),
Provider(create: (context) => SomeClassToBeUsedAsSingleton()),
],
child: MyApp(),
),
);
}
Widget build(BuildContext context) {
var instance = Provider.of<SomeClassToBeUsedAsSingleton>(context);
...
答案 8 :(得分:3)
这就是我在项目中实现单例的方式
灵感来自扑扑的火力== 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();
}
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);
答案 9 :(得分:3)
在阅读所有替代方案之后,我想到了这一点,这让我想起了“经典单身人士”:
class AccountService {
static final _instance = AccountService._internal();
AccountService._internal();
static AccountService getInstance() {
return _instance;
}
}
答案 10 :(得分:2)
** Dart Sound Null Safety 中的 Sigleton 范式**
<块引用>这段代码展示了如何在 dart 中实现单例 这通常用于我们每次都必须使用类的相同对象的情况,例如。在数据库事务中。
http://prediction_new_name
答案 11 :(得分:2)
从 Dart 2.13
版本开始,使用 late
关键字非常容易。 Late
关键字允许我们延迟实例化对象。
举个例子,你可以看看:
class LazySingletonExample {
LazySingletonExample._() {
print('instance created.');
}
static late final LazySingletonExample instance = LazySingletonExample._();
}
<块引用>
注意:请记住,当您调用lazy instance
字段时,它只会被实例化一次。
答案 12 :(得分:2)
修改过的@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';
答案 13 :(得分:1)
这也是创建单例类的一种方式
class Singleton{
Singleton._();
static final Singleton db = Singleton._();
}
答案 14 :(得分:1)
这是一个结合其他解决方案的简洁示例。访问单例可以通过以下方式完成:
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
}
答案 15 :(得分:0)
实例后无法更改对象的单个
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}
答案 16 :(得分:0)
这是一个简单的答案:
class Singleton {
static Singleton _instance;
Singleton._() {}
static Singleton get getInstance => _instance = _instance ?? Singleton._();
}
答案 17 :(得分:0)
你好,这样的事情怎么办?非常简单的实现,Injector本身是单例的,并且还向其中添加了类。当然可以很容易地扩展。如果您正在寻找更复杂的东西,请查看以下软件包:https://pub.dartlang.org/packages/flutter_simple_dependency_injection
<script>
App.route('login', {some: 'props'});
</script>
答案 18 :(得分:0)
我在 dart 上使用这个简单的模式,之前在 Swift 上使用过。我喜欢它简洁而且只有一种使用方式。
class Singleton {
static Singleton shared = Singleton._init();
Singleton._init() {
// init work here
}
void doSomething() {
}
}
Singleton.shared.doSomething();
答案 19 :(得分:0)
由于我不太喜欢使用new
关键字或其他构造函数(例如单例调用),因此我更喜欢使用称为inst
的静态吸气剂:
// 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));
答案 20 :(得分:0)
这应该有效。
class GlobalStore {
static GlobalStore _instance;
static GlobalStore get instance {
if(_instance == null)
_instance = new GlobalStore()._();
return _instance;
}
_(){
}
factory GlobalStore()=> instance;
}
答案 21 :(得分:0)
您可以只使用常量构造函数。
class Singleton {
const Singleton(); //Constant constructor
void hello() { print('Hello world'); }
}
示例:
Singleton s = const Singleton();
s.hello(); //Hello world
根据文档:
<块引用>常量构造函数
如果您的类产生永远不会改变的对象,您可以将这些对象设为编译时常量。为此,请定义一个 const 构造函数并确保所有实例变量都是最终变量。