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


当前回答

使用空安全操作符和工厂构造函数可以更好地创建单例对象。

class Singleton {
  static Singleton? _instance;

  Singleton._internal();

  factory Singleton() => _instance ??= Singleton._internal();
  
  void someMethod() {
    print("someMethod Called");
  }
}

用法:

void main() {
  Singleton object = Singleton();
  object.someMethod(); /// Output: someMethod Called
}

注意:? ?是一个Null感知操作符,如果左边值为Null,它将返回右边的值,这意味着在我们的例子中_instance ??Singleton._internal();, Singleton._internal()将在第一次调用object时返回,rest _instance将返回。

其他回答

因为我不太喜欢使用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 AccountService {
  static final _instance = AccountService._internal();

  AccountService._internal();

  static AccountService getInstance() {
    return _instance;
  }
}

我觉得阅读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在他的游戏编程模式书中对单身人士的看法。

实例化后不能更改对象的单例

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}

你好,这样的东西怎么样?非常简单的实现,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;
  }
}