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


当前回答

在Dart中创建Singleton没有什么棘手的。您可以在顶级(全局)位置声明任何变量,默认情况下这是一个单例。也可以将变量声明为类的静态成员。这是单元素a。

class A {}

final a = A();

However, the above does not allow you to replace the instance for testing. The other issue is that as the app grows in complexity, you may want to convert global or static variables to transient dependencies inside your classes. If you use dependency injection, you can change a dependency inside your composition at any time. This is an example of using ioc_container to configure a singleton instance of A in the root of an app. You can change this to a transient dependency any time by using add instead of addSingletonService

import 'package:ioc_container/ioc_container.dart';

class A {}

void main(List<String> arguments) {
  final builder = IocContainerBuilder()..addSingletonService(A());
  final container = builder.toContainer();
  final a1 = container<A>();
  final a2 = container<A>();
  print(identical(a1, a2));
}

上面打印为真,因为应用程序只会生成一个A实例。

其他回答

因为我不太喜欢使用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));

这里有一个简单的答案:

类应具有其类型的私有和静态属性。 构造函数应该是私有的,以防止外部对象初始化。 检查实例是否为空,如果是,创建一个实例并返回,否则返回现有实例。

实现(延迟加载)

class Singleton {
  static Singleton? _instance;

  Singleton._();

  static Singleton get instance => _instance ??= Singleton._();

  void someMethod(){
    ...
  }

  ...
}

实现(急装)

class Singleton {
  static Singleton _instance = Singleton._();

  Singleton._();

  static Singleton get instance => _instance;

  void someMethod(){
    ...
  }

  ...
}

使用

Singleton.instance.someMethod();

多亏了Dart的工厂构造函数,构建一个单例对象变得很容易:

class Singleton {
  static final Singleton _singleton = Singleton._internal();

  factory Singleton() {
    return _singleton;
  }

  Singleton._internal();
}

你可以这样构造它

main() {
  var s1 = Singleton();
  var s2 = Singleton();
  print(identical(s1, s2));  // true
  print(s1 == s2);           // true
}

在阅读了所有的选项后,我想到了这个,这让我想起了一个“经典的单例”:

class AccountService {
  static final _instance = AccountService._internal();

  AccountService._internal();

  static AccountService getInstance() {
    return _instance;
  }
}

这是我做单例的方式,接受参数(你可以直接粘贴到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?类型(空安全)。