Flutter 中具有 NullSafety 的单例类

Mor*_*rez 10 dart flutter dart-null-safety

我有这个类,它通过使用工厂构造函数获取一些参数,如果实例为空,将创建一个新对象;如果它不为空,则将返回实例的值,因此我们始终收到相同的对象(单例)。这就是我在启用 dart 的空安全功能之前使用单例模式的方式。

class GuestUser extends User {
  static GeustUser _instance;


  factory GuestUser(
      {required String firstName,
      required String lastName,
      required String email,
      required Address address,
      required PaymentInfo paymentInfo}) {
    if (_instance == null) {
      _instance =
          GuestUser._(firstName, lastName, email, address, paymentInfo);
    }
    return _instance;
  }
Run Code Online (Sandbox Code Playgroud)

现在启用空安全后,我收到此错误:

The non-nullable variable '_instance' must be initialized.
Try adding an initializer expression.
Run Code Online (Sandbox Code Playgroud)

if (_instance == null)不再需要了。

_instance如果我这样定义: static late final GuestUser _instance;那么我不能使用 来if (_instance == null)仅在需要时创建 _instance 。所以我必须删除 if 语句并在每次调用工厂构造函数时创建一个新实例。

如何解决这个问题并创建启用空安全的单例类?

我想到了这个解决方案来使用布尔变量跟踪实例:

static late final GeustUser _instance;
static bool _isInstanceCreated = false;

  factory GuestUser(
      {required String firstName,
      required String lastName,
      required String email,
      required Address address,
      required PaymentInfo paymentInfo}) {
    if (_isInstanceCreated == false) {
      _instance =
          GuestUser._(firstName, lastName, email, address, paymentInfo);
    }
    _isInsanceCreated = true;
    return _instance;
  }
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有一种方法可以在不定义新变量的情况下通过使用空安全的功能来做到这一点

jul*_*101 4

你的单例有点奇怪,因为你正在接受的参数只会在第一次调用时使用。这不是一个很好的模式,因为如果您想将它用于两个不同的来宾用户,它可能会带来一些惊喜。

在您的示例中,仅用作GuestUser?的类型是有意义的_instance。Dart 中默认不可为 null 不应该被视为null不好的使用,并且您绝对应该null在有意义的地方使用它(特别是如果我们可以阻止引入bool变量来指示变量是否已设置)。在您的示例中,_instance在第一次初始化之前为 null。

我们使用运算符的示例??=。该运算符将检查是否为,如果是_instance,则将变量分配给通过调用构造函数创建的对象。此后它将返回 的值。如果does 已经有一个值(not ),则仅返回该值而不调用构造函数。nullnullGuestUser.__instance_instancenullGuestUser._

class GuestUser extends User {
  static GuestUser? _instance;

  factory GuestUser(
          {required String firstName,
          required String lastName,
          required String email,
          required Address address,
          required PaymentInfo paymentInfo}) =>
      _instance ??=
          GuestUser._(firstName, lastName, email, address, paymentInfo);
}
Run Code Online (Sandbox Code Playgroud)

如果您有一个更传统的单例,您可以static final在定义中创建实例的位置创建一个变量。但这不允许参数。