我读了这些帖子:
我很难理解以下创建单例的方式之间的区别:
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
是可选的使工厂构造函数现在不必要了。在您无法执行上述SingletonTwo
或SingletonThree
之类的事情之前?
您也可以将
static final DbHelper _db = new DbHelper._constr();
更改为static final DbHelper singleton = new DbHelper._constr();
并删除我在我的建议中提出的单例消气剂 回答。这取决于您的用例。您可能无法使用 字段初始值设定项,如果您需要其他配置值来创建 实例。在您的示例中就足够了。
上述每个单例模式(SingletonOne,SingletonTwo和SingletonThree)的用例是什么?看看每个例子都是有帮助的。如果您想隐藏该类是单例的事实(如here所述),那么工厂模式是否有用?
答案 0 :(得分:1)
由于 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!;
}
}
答案 1 :(得分:0)
与Günter Zöchbauer stated in the comments一样,您列出的创建单例的三种方式都是相同的。根据个人喜好选择一个。
我要添加一些其他注释:
SingletonOne
实例化时与任何其他类相似。因此,如果您想隐藏它是单身的事实(并保留选择使其将来不再是单身)的事实,可以使用此选项。您还可以在构造函数中传递参数。SingletonTwo
将允许您在返回实例之前执行其他工作。SingletonThree
是最短的,在所有其他条件相同的情况下,我的书中希望使用简短的简洁代码。我将其作为临时答案提交,希望获得反馈。也欢迎其他更完整/更好的答案。