我有一个数据课:
class Data {
int a;
int b;
Data({this.a, this.b})
}
我只想为整个应用创建此类的一个对象。
所有其他类都应该能够实例化Data类,但是在内部它应该返回相同的对象,该对象应该是常量。
是否可以将上述限制应用于Dart中的课程?
答案 0 :(得分:1)
有两种方法可以实现此目的。一种是使用常规旧常量:
class Data {
final int a;
final int b;
const Data({this.a, this.b});
}
这看起来似乎不符合您要查找的约束,但实际上Dart常量有一个微妙的功能,称为 canonical实例。这意味着程序中声明的每个具有相同字段值的const
值在编译时都会变成一个已知值。然后在代码中常量被“实例化”的任何地方都引用此值:
const a = Data(a: 1, b: 3);
const b = Data(a: 1, b: 3);
const c = Data(a: 2, b: 4);
// Both `a` and `b` here point to the same object in memory.
// `c` is a different object because the values passed as parameters are different.
另一种方法是使用单例。基本上,这需要一个普通实例,并将其视为整个类的静态值。在Dart中执行此操作的最简单方法是使用未命名的工厂构造函数:
class Data {
int a;
int b;
Data _instance;
Data._({this.a, this.b});
factory Data({int a, int b}) {
_instance ??= new Data._(a: a, b: b);
return _instance;
}
}
上面的代码创建了一个懒惰实例化的单例,这基本上意味着该实例只有在实际需要时才被创建。使用工厂方法意味着您可以指定实际返回哪个实例,这意味着我们每次都可以返回_instance
。这意味着所有创建新Data
实例的代码都将返回相同的_instance
值:
Foo a = Data(a: 1, b: 3);
Foo b = Data(a: 1, b: 3);
Foo c = Data(a: 2, b: 4);
// a, b, and c are all the same instance of Foo
(不过,在这种方法中要注意的一点是,_instance
仅在工厂调用构造函数时才创建,而此时a
和{{ 1}},这意味着从那时起,每次调用构造函数时,b
和a
的参数都会被忽略,例如在上面的示例中,为b
和a
。这就是为什么单例对于带有参数的服务类不是一个好选择。)
不过,还有更多建议的方法。一种是使用类似get_it包的服务定位器来创建普通实例,然后以分离的方式将其公开给整个包:
b
现在您可以调用import 'package:get_it/get_it.dart';
void createSingleton() {
GetIt.instance.registerSingleton(Data(a: 1, b: 3));
}
来检索相同的值:
get
这似乎需要更多工作,但是通过不将代码绑定到特定类型或实现上,可以使代码更加灵活。在实现诸如依赖注入和单元测试之类的东西时,这很方便。