具有 NullSafety 的 Flutter 中的单例 Class
Singleton Class in Flutter with NullSafety
我有这个class,它通过使用工厂构造函数接受一些参数,如果实例为空,将创建一个新对象;如果它不为 null,则实例的值将被返回,因此我们始终接收到相同的对象(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.
也不再需要 if (_instance == null)
。
如果我这样定义 _instance
: static late final GuestUser _instance;
那么我不能使用 if (_instance == null)
仅在需要时创建 _instance。所以每次调用工厂构造函数时我都必须删除 if 语句并创建一个新实例。
如何解决这个问题并创建一个启用空安全的单例 class?
我想到了这个解决方案来跟踪带有布尔变量的实例:
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;
}
但我想知道是否有一种方法可以在不定义新变量的情况下使用 null-safety
你的单身人士有点奇怪,因为你接受的参数只会在第一次调用时使用。这不是一个很好的模式,因为它可以给一些惊喜,例如您想将它用于两个不同的来宾用户。
在您的示例中,仅使用 GuestUser?
作为 _instance
的类型是有意义的。在 Dart 中默认不可为空不应该被视为使用 null
是不好的,你绝对应该在有意义的地方使用 null
(特别是如果我们可以防止引入 bool
变量以指示是否已设置变量)。在您的示例中,_instance
在第一次初始化之前为 null。
我们使用 ??=
运算符的示例。运算符将检查 _instance
是否为 null
,如果是 null
,它将把变量分配给通过调用构造函数 GuestUser._
创建的对象。此后它将 return 的值 _instance
。如果 _instance
确实已经有一个值(不是 null
),这个值将只是 returned 而不会调用 GuestUser._
构造函数。
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);
}
如果你有一个更传统的单例,你可以在定义中创建实例的地方创建一个 static final
变量。但这不允许参数。
正如提到的,你的单身人士实际上很奇怪,因为通常你会做这样的事情:
class Foo {
static final instance = Foo._();
Foo._();
}
但是,您不能用参数实例化它。为此,您可以这样做:
class Bar {
static Bar? instance;
Bar._(int i);
factory Bar.fromInt(int i) {
var bar = Bar._(i);
instance = bar;
return bar;
}
void display() => print('Bar instance');
}
void main() {
final nullableBar = Bar.instance;
final nonNullableBar = Bar.fromInt(0);
nullableBar!.display(); // Runtime error as Bar.instance is used before Bar.fromMap(0)
nonNullableBar.display(); // No error
}
您可以使用相同的传统方式创建单例。您只需将空安全运算符放在正确的位置即可。
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!;
}
}
你得到的是延迟初始化的一部分,使用这种方法我们在运行时创建实例,而不是在初始化时。
最后,使用 null 感知运算符将解决您的问题,最好使用工厂构造函数来初始化对象。
class GuestUser {
static GuestUser? _instance;
GuestUser._(
String firstName,
String lastName,
String email,
String address,
String paymentInfo);
factory GuestUser(
{required String firstName,
required String lastName,
required String email,
required String address,
required String paymentInfo}) {
_instance ??=
GuestUser._(firstName, lastName, email, address, paymentInfo);
return _instance!;
}
///.. Rest code
}
像这样创建对象
GuestUser user = GuestUser(firstName: "jitesh", lastName: "mohite", email: "jitesh@gmail.com", address: "Universe", paymentInfo: "As you like");
我有这个class,它通过使用工厂构造函数接受一些参数,如果实例为空,将创建一个新对象;如果它不为 null,则实例的值将被返回,因此我们始终接收到相同的对象(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.
也不再需要 if (_instance == null)
。
如果我这样定义 _instance
: static late final GuestUser _instance;
那么我不能使用 if (_instance == null)
仅在需要时创建 _instance。所以每次调用工厂构造函数时我都必须删除 if 语句并创建一个新实例。
如何解决这个问题并创建一个启用空安全的单例 class?
我想到了这个解决方案来跟踪带有布尔变量的实例:
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;
}
但我想知道是否有一种方法可以在不定义新变量的情况下使用 null-safety
你的单身人士有点奇怪,因为你接受的参数只会在第一次调用时使用。这不是一个很好的模式,因为它可以给一些惊喜,例如您想将它用于两个不同的来宾用户。
在您的示例中,仅使用 GuestUser?
作为 _instance
的类型是有意义的。在 Dart 中默认不可为空不应该被视为使用 null
是不好的,你绝对应该在有意义的地方使用 null
(特别是如果我们可以防止引入 bool
变量以指示是否已设置变量)。在您的示例中,_instance
在第一次初始化之前为 null。
我们使用 ??=
运算符的示例。运算符将检查 _instance
是否为 null
,如果是 null
,它将把变量分配给通过调用构造函数 GuestUser._
创建的对象。此后它将 return 的值 _instance
。如果 _instance
确实已经有一个值(不是 null
),这个值将只是 returned 而不会调用 GuestUser._
构造函数。
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);
}
如果你有一个更传统的单例,你可以在定义中创建实例的地方创建一个 static final
变量。但这不允许参数。
正如
class Foo {
static final instance = Foo._();
Foo._();
}
但是,您不能用参数实例化它。为此,您可以这样做:
class Bar {
static Bar? instance;
Bar._(int i);
factory Bar.fromInt(int i) {
var bar = Bar._(i);
instance = bar;
return bar;
}
void display() => print('Bar instance');
}
void main() {
final nullableBar = Bar.instance;
final nonNullableBar = Bar.fromInt(0);
nullableBar!.display(); // Runtime error as Bar.instance is used before Bar.fromMap(0)
nonNullableBar.display(); // No error
}
您可以使用相同的传统方式创建单例。您只需将空安全运算符放在正确的位置即可。
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!;
}
}
你得到的是延迟初始化的一部分,使用这种方法我们在运行时创建实例,而不是在初始化时。
最后,使用 null 感知运算符将解决您的问题,最好使用工厂构造函数来初始化对象。
class GuestUser {
static GuestUser? _instance;
GuestUser._(
String firstName,
String lastName,
String email,
String address,
String paymentInfo);
factory GuestUser(
{required String firstName,
required String lastName,
required String email,
required String address,
required String paymentInfo}) {
_instance ??=
GuestUser._(firstName, lastName, email, address, paymentInfo);
return _instance!;
}
///.. Rest code
}
像这样创建对象
GuestUser user = GuestUser(firstName: "jitesh", lastName: "mohite", email: "jitesh@gmail.com", address: "Universe", paymentInfo: "As you like");