单例模式确保只创建一个类的实例。我如何在达特建立这个?


当前回答

我在dart和之前的Swift上使用这个简单的模式。我喜欢它的简洁和只有一种使用方式。

class Singleton {
  static Singleton shared = Singleton._init();
  Singleton._init() {
    // init work here
  }

  void doSomething() {
  }
}

Singleton.shared.doSomething();

其他回答

下面是一个组合了其他解决方案的简洁示例。可以通过以下方式访问单例对象:

使用指向实例的单例全局变量。 通用单例。模式实例。 使用默认构造函数,它是一个返回实例的工厂。

注意:您应该只实现三个选项中的一个,以便使用单例的代码保持一致。

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
}

你可以只使用Constant构造函数。

class Singleton {
  const Singleton(); //Constant constructor
  
  void hello() { print('Hello world'); }
}

例子:

Singleton s = const Singleton();
s.hello(); //Hello world

根据文件:

恒定的构造函数 如果类生成永不更改的对象,则可以使这些对象成为编译时常量。为此,定义一个const构造函数,并确保所有实例变量都是final变量。

这是我做单例的方式,接受参数(你可以直接粘贴到https://dartpad.dev/):

void main() {
  
  Logger x = Logger('asd');
  Logger y = Logger('xyz');
  
  x.display('Hello');
  y.display('Hello There');
}


class Logger{
  
  
  Logger._(this.message);
  final String message;
  static Logger _instance = Logger._('??!?*');
  factory Logger(String message){
    if(_instance.message=='??!?*'){
      _instance = Logger._(message);
    }
    return _instance;
  }
  
  void display(String prefix){
    print(prefix+' '+message);
  }
  
}

输入:

Hello asd
Hello There asd

“? ? ! ?*'你看到的只是一个工作区,我做了初始化_instance变量暂时没有使它成为一个Logger?类型(空安全)。

我觉得阅读new Singleton()不是很直观。你必须阅读文档才能知道new实际上并没有像通常那样创建一个新实例。

这里有另一种方法来做单例(基本上是Andrew上面说的)。

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来实现单例。即的事情。单例,而不是顶级getter。

还可以阅读Bob Nystrom在他的游戏编程模式书中对单身人士的看法。

这也是一种创建Singleton类的方法

class Singleton{
  Singleton._();
  static final Singleton db = Singleton._();
}