在Dart中,是否可以在单例中传递参数?

27
class Peoples {
  late int id;
  late String name;

  static final Peoples _inst = Peoples._internal();

  Peoples._internal();

  factory Peoples() {
    return _inst;
  }
}

我有一个单例类,它确保只创建一个类的实例。因此,即使有人尝试进行实例化,他们也会使用同一个实例。而且,我可以创建和设置值,例如:

  Peoples ps1 = Peoples();
  Peoples ps2 = Peoples();

  ps1.id = 1;
  ps1.name = "First";

  ps2.id = 2;
  ps2.name = "Second";

能否实例化并设置如下值:

  Peoples ps1 = Peoples(1, "First");
  Peoples ps2 = Peoples(2, "Second");

现在,“ps1”和“ps2”都将拥有(2,“Second”)。

5个回答

55
当然!你需要将参数传递给工厂方法,然后使用所引用的实例来更新属性。
例如,你可能有:
class Peoples {
  late int id;
  late String name;

  static final Peoples _inst = Peoples._internal();

  Peoples._internal();

  factory Peoples() {
    return _inst;
  }
}

如果您使用我的解决方案,则会得到

class Peoples {
  late int id;
  late String name;

  static final Peoples _inst = Peoples._internal();

  Peoples._internal();

  factory Peoples({int id, String name}) {
    _inst.id = id
    _inst.name = name
    return _inst;
  }
}

通过这个,你的问题应该得到了答案。 关于工厂和参数的更多信息,请访问 https://dart.dev/guides/language/language-tour

工作示例

class Peoples {
  late int id;
  late String name;

  static final Peoples _inst = Peoples._internal();

  Peoples._internal();
  

  factory Peoples(int id, String name) {
    _inst.id = id;
    _inst.name = name;
    return _inst;
  }
}

void main() {
  print("Instance of = " + Peoples(0, "Dylan").name);
  print("Instance of = " + Peoples(1, "Joe").name);
  print("Instance of = " + Peoples(2, "Maria").name);
}

10
有没有办法使用final int id和final String name来完成这个操作? - Anton

4

我想分享一种通过传递参数创建单例并在创建后“锁定”其值的方法。

class People {
  static final People _inst = People._internal();
  People._internal();

  factory People(int id, String name) {
    assert(!_inst._lock, "it's a singleton that can't re-defined");
    _inst.id = id;
    _inst.name = name;
    _inst._lock = true;
    return _inst;
  }
  
  int id;
  String name;
  bool _lock = false;
}

void main() {
  var people = People(0, 'Dylan');
  try{
    print('Instance of = ' + People(0, 'Joe').name);
    print('Instance of = ' + People(1, 'Maria').name);
    print('Instance of = ' + People(2, 'Ete sech').name);
  } finally {
    print('Instance of = ' + people.name);
  }
}

有一个有点奇怪的例子,如果我想传入一个有效人员列表,会是什么样子呢?我在让这个模型工作方面遇到了困难。 - Ride Sun
嗯,对于这种情况,这个模型可能是无用的,但是想象一下单例模式,您想保存不会修改的信息,它只会被读取。就像当您想在应用程序启动后保存用户,并且不想使用共享首选项或云来保存和请求有关其信息时。我认为这将是有用的。 - José Luna
2
断言仅在调试模式下起作用。因此,在生产模式下它仍会重新分配这些值。 - Əlişiram

3

Dart / Flutter带有不可更改参数的单例模式

这是一个类的实例,在第一次构造后始终返回相同的实例。

该类字段不是final或late,而是可为空的。

  • 工厂构造函数只允许实例变量在它们为null时更改。
  • 如果未提供实例变量,则工厂构造函数会为其提供默认值。
class SingletonClass {
  bool? debugMode;

  /// Always return a singleton instance
  static final SingletonClass _instance = SingletonClass._internal();

  /// Internal Constructor
  SingletonClass._internal();

  /// Consumable Constructor
  factory SingletonClass({bool debugMode = false}) {
    // Set null class parameters
    _instance.debugMode ??= debugMode;

    return _instance;
  }
}

// Initialize the singleton
SingletonClass singletonClass = SingletonClass(debugMode: true);
debugPrint("debugMode: ${singletonClass.debugMode}");

/// Attempt to create another instance with different arguments / field values
SingletonClass singletonClass2 = SingletonClass(debugMode: false);
debugPrint("debugMode2: ${singletonClass2.debugMode}");

控制台日志输出

flutter: debugMode: true
flutter: debugMode2: true

尽管第二次尝试创建该类时将其声明为false,但debugMode仍保持为true。对于singletonClasssingletonClass2都返回相同的类实例。

您可以在代码的任何位置声明一个新的SingletonClass类型变量,并且它将是相同的。


1

这个答案 不能在我的计算机上运行,2022年3月29日

计算机显示:“非空实例字段'id'必须初始化。”

我无法发表评论,所以写下了这个答案:

在成员变量前添加关键字 late 将会有帮助:

class Peoples {
  late int id;
  late String name;

  static final Peoples _inst = Peoples._internal();

  Peoples._internal();


  factory Peoples(int id, String name) {
    _inst.id = id;
    _inst.name = name;
    return _inst;
  }
}


0
class BasketService {
  late String basketId;

  static final BasketService _instance = BasketService._internal();
  BasketService._internal();

  factory BasketService(String basketUniqueId) {
    _instance.basketId = basketUniqueId;
    return _instance;
  }
  factory BasketService.getInstance() {
    return _instance;
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接