你如何在Dart中建立一个单身人士?

时间:2012-09-29 02:59:52

标签: dart singleton

单例模式确保只创建一个类的一个实例。我如何在Dart中构建它?

22 个答案:

答案 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中创建单例的几种不同方式的比较。

1。工厂构造函数

class SingletonOne {

  SingletonOne._privateConstructor();

  static final SingletonOne _instance = SingletonOne._privateConstructor();

  factory SingletonOne(){
    return _instance;
  }

}

2。带有getter的静态字段

class SingletonTwo {

  SingletonTwo._privateConstructor();

  static final SingletonTwo _instance = SingletonTwo._privateConstructor();

  static SingletonTwo get instance { return _instance;}

}

3。静态字段

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 包进行状态管理,那么创建和使用单例非常简单。

  1. 创建实例
<块引用>
  void main() {
      runApp(
        MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (context) => SomeModel()),
            Provider(create: (context) => SomeClassToBeUsedAsSingleton()),
          ],
          child: MyApp(),
        ),
      );
    }
  1. 获取实例
<块引用>
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 构造函数并确保所有实例变量都是最终变量。