Flutter 具有零安全性的颤振中的单粒子类

Flutter 具有零安全性的颤振中的单粒子类,flutter,dart,dart-null-safety,Flutter,Dart,Dart Null Safety,我有一个类,它使用工厂构造函数获取一些参数,如果实例为null,将创建一个新对象;如果不为null,则返回instance的值,因此我们始终接收相同的对象(Singleton)。在启用dart的空安全特性之前,我就是这样使用单例模式的 class GuestUser extends User { static GeustUser _instance; factory GuestUser( {required String firstName, required

我有一个类,它使用工厂构造函数获取一些参数,如果实例为null,将创建一个新对象;如果不为null,则返回instance的值,因此我们始终接收相同的对象(Singleton)。在启用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;
  }
现在启用空安全性后,出现以下错误:

The non-nullable variable '_instance' must be initialized.
Try adding an initializer expression.
如果不再需要(\u instance==null),也可以使用

如果我这样定义
\u实例
static late final GuestUser\u实例
那么我不能使用
if(\u instance==null)
仅在需要时创建\u实例。因此,每次调用工厂构造函数时,我都必须删除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;
  }

但是我想知道是否有一种方法可以做到这一点,而不需要定义新的变量,并且通过使用空安全性的特性,您的单例有点奇怪,因为您使用的参数只有在第一次调用它时才会使用。这不是一个很好的模式,因为如果您想为两个不同的来宾用户使用它,它会给您带来一些惊喜

在您的示例中,使用
GuestUser?
作为
\u实例的类型是有意义的。Dart中默认情况下不可为空不应被视为使用
null
是不好的,您应该在有意义的地方使用
null
(特别是如果我们可以防止引入
bool
变量来指示是否设置了变量)。在您的示例中,
\u实例
在第一次初始化之前为空

使用
??=
运算符的示例。操作员将检查
\u实例
是否为
null
,如果是
null
,则将变量分配给通过调用构造函数
GuestUser创建的对象。此后,它将返回
\u instance
的值。如果
\u实例
已经有一个值(不是
null
),则只返回该值,而不调用
GuestUser.\u
构造函数

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);
}
如果使用更传统的单例,则可以在定义中创建实例的位置创建一个
静态final
变量。但这不允许参数。

如前所述,您的单例实际上很奇怪,因为通常您会执行以下操作:

class-Foo{
静态最终实例=Foo.uz();
福;
}
但是,您不能用参数来实例化它。为此,您可以这样做:

类栏{
静态条实例;
巴(国际一级);
工厂条形图fromInt(int i){
var bar=bar.Ui;
实例=bar;
返回杆;
}
void display()=>打印('Bar实例');
}
void main(){
final nullableBar=Bar.instance;
最终不可为NullBar=Bar.fromInt(0);
nullableBar!.display();//运行时错误,因为在Bar.fromMap(0)之前使用了Bar.instance
nonNullableBar.display();//无错误
}

您可以使用相同的传统方法创建单例。您只需将空安全运算符放在正确的位置

class MySingleton {
  // make this nullable by adding '?'
  static MySingleton? _instance;

  MySingleton._() {
    // initialization and stuff
  }

  factory MySingleton() {
    if (_instance == null) {
      _instance = new MySingleton._();
    }
    // since you are sure you will return non-null value, add '!' operator
    return _instance!;
  }
}

这很好,谢谢,但最好将映射传递给工厂,因为名称是fromMap,但传递的是int。这当然有效,但在本例中使用映射更好。@Morez最初我打算使用
map
(这是常规模式),但为了使代码简短,我使用了
int
。哎呀,我刚才注意到我正在使用
fromMap
word。实际上我应该更改代码。哈哈。谢谢你的关注!