如何将类实例的创建限制为飞镖中的实例?

  • 本文关键字:实例 飞镖 创建 class dart
  • 更新时间 :
  • 英文 :


我有一个类数据:

class Data {
int a;
int b;
Data({this.a, this.b})
}

我只想为整个应用程序创建此类的一个对象。

所有其他类都应该能够实例化 Data 类,但在内部它应该返回相同的对象,该对象应该是常量。

有没有办法将上述限制应用于 Dart 中的类?

有几种方法可以实现此目的。一种是使用常规的旧常量:

class Data {
final int a;
final int b;
const Data({this.a, this.b});
}

这可能看起来不适用您正在寻找的特征,但实际上 Dart 常量有一个微妙的特征,称为规范实例。这意味着在程序中声明的具有相同字段值的每个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仅在第一次调用工厂构造函数时创建,并且这是采用ab值的时候。这意味着从那时起,每次调用构造函数时,都会忽略ab的参数,例如在上面的示例中,为ab传递了不同的值。这就是为什么对于采用参数的服务类,单例不是一个好的选择。

不过,有更可取的方法可以做到这一点。一种是使用像 get_it 包这样的服务定位器创建一个普通实例,然后以解耦的方式将其公开给整个包:

import 'package:get_it/get_it.dart';
void createSingleton() {
GetIt.instance.registerSingleton(Data(a: 1, b: 3));
}

现在您可以检索调用get的相同值:

final data = GetIt.instance.get<Data>();

这看起来工作量更大,但它通过不将代码绑定到特定类型或实现,使代码更加灵活。这在实现依赖注入和单元测试等内容时会派上用场。

最新更新