比较在 Dart 中创建单例的方法

Posted

技术标签:

【中文标题】比较在 Dart 中创建单例的方法【英文标题】:Comparing ways to create singletons in Dart 【发布时间】:2019-06-01 03:33:14 【问题描述】:

我读过这些帖子:

How do you build a Singleton in Dart? How to implement Singleton pattern in Dart using factory constructors? Object Structures in 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;

问题

Günter Zöchbauer said 关于this question:

不需要使用工厂构造函数。工厂 当 new 还不是可选的时候,构造函数很方便,因为那时 它new MyClass() 适用于构造函数返回的类 每次或类返回缓存实例的新实例。 知道对象的方式和时间不是调用者的责任 实际上是创建的。

我不明白 new 现在是可选的如何使得工厂构造函数现在变得不必要了。在您无法执行上述SingletonTwoSingletonThree 之类的操作之前?

Günter Zöchbauer also said:

您还可以将 static final DbHelper _db = new DbHelper._constr(); 更改为 static final DbHelper singleton = new DbHelper._constr(); 并删除我在我的 回答。这取决于您的用例。您可能无法使用 如果您需要其他配置值来创建字段初始值设定项 实例。不过,在您的示例中就足够了。

上述每个单例模式(SingletonOne、SingletonTwo 和 SingletonThree)的用例是什么?查看每个示例会很有帮助。如果您想隐藏类是单例的事实(如here 所述),工厂模式不是很有用吗?

【问题讨论】:

都是一样的。只使用你最喜欢的。 【参考方案1】:

作为Günter Zöchbauer stated in the comments,您列出的创建单例的三种方式中的每一种都是相同的。使用您的个人喜好选择一个。

我将添加一些额外的注释:

SingletonOne 实例化时看起来像任何其他类。因此,如果您想隐藏它是单例的事实(并保留将来使其不再是单例的选项),则可以使用这个。您也可以在构造函数中传入参数。 SingletonTwo 将允许您在返回实例之前做其他工作。 SingletonThree 是最短的,并且在我的书中需要简洁干净的代码,所有其他条件都相同。

【讨论】:

【参考方案2】:

由于 Dart 允许根级变量,因此可以拥有一个非常好的延迟加载单例:

final store = _Store();

class _Store 
//

限制

与您的其他三个示例一样,如果您需要异步构造,这将不起作用。此外,与 SingletonTwo 和 SingletonThree 一样,您不能从调用范围传入任何参数。

对于需要异步构造和参数的单例,我会使用这样的东西:

class StoreService 
  static StoreService? _instance;

  StoreService._() 

  static Future<StoreService> instance() async 
    // we can await things here
    
    if (_instance == null) 
      _instance = StoreService._();
    

    return _instance!;
  

【讨论】:

以上是关于比较在 Dart 中创建单例的方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中创建单例

如何在 Angular 2 中创建单例服务?

在多处理中创建单例类

在初始化列表中创建单例对象会导致访问冲突(仅限发布模式)

java中单例设计模式

性能比较好的单例写法