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

时间:2020-02-16 01:59:42

标签: class dart

我有一个数据课:

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

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

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

是否可以将上述限制应用于Dart中的课程?

1 个答案:

答案 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}},这意味着从那时起,每次调用构造函数时,ba的参数都会被忽略,例如在上面的示例中,为ba。这就是为什么单例对于带有参数的服务类不是一个好选择。)

不过,还有更多建议的方法。一种是使用类似get_it包的服务定位器来创建普通实例,然后以分离的方式将其公开给整个包:

b

现在您可以调用import 'package:get_it/get_it.dart'; void createSingleton() { GetIt.instance.registerSingleton(Data(a: 1, b: 3)); } 来检索相同的值:

get

这似乎需要更多工作,但是通过不将代码绑定到特定类型或实现上,可以使代码更加灵活。在实现诸如依赖注入和单元测试之类的东西时,这很方便。