Подтвердить что ты не робот

Как вы строите Синглтон в Дарт?

Шаблон singleton обеспечивает создание только одного экземпляра класса. Как это сделать в Dart?

4b9b3361

Ответ 1

Благодаря Dart фабричным конструкторам легко создать синглтон:

class Singleton {
  static final Singleton _singleton = Singleton._internal();

  factory Singleton() {
    return _singleton;
  }

  Singleton._internal();
}

Вы можете создать его с помощью new

main() {
  var s1 = Singleton();
  var s2 = Singleton();
  print(identical(s1, s2));  // true
  print(s1 == s2);           // true
}

Ответ 2

Вот сравнение нескольких разных способов создания синглтона в Dart.

1. Фабричный конструктор

class SingletonOne {

  SingletonOne._privateConstructor();

  static final SingletonOne _instance = SingletonOne._privateConstructor();

  factory SingletonOne(){
    return _instance;
  }

}

2. Статическое поле с геттером

class SingletonTwo {

  SingletonTwo._privateConstructor();

  static final SingletonTwo _instance = SingletonTwo._privateConstructor();

  static SingletonTwo get instance { return _instance;}

}

3. Статическое поле

class SingletonThree {

  SingletonThree._privateConstructor();

  static final SingletonThree instance = SingletonThree._privateConstructor();

}

Как создать экземпляр

Вышеуказанные синглтоны создаются следующим образом:

SingletonOne one = SingletonOne();
SingletonTwo two = SingletonTwo.instance;
SingletonThree three = SingletonThree.instance;

Замечания:

Первоначально я задал это как вопрос, но обнаружил, что все методы, перечисленные выше, действительны, и выбор во многом зависит от личных предпочтений.

Ответ 3

Я не нахожу это очень интуитивным чтением new Singleton(). Вы должны прочитать документы, чтобы знать, что new самом деле не создает новый экземпляр, как обычно.

Вот еще один способ сделать синглтоны (в основном то, что Андрей сказал выше).

Библиотека /thing.dart

library thing;

final Thing thing = new Thing._private();

class Thing {
   Thing._private() { print('#2'); }
   foo() {
     print('#3');
   }
}

main.dart

import 'package:thing/thing.dart';

main() {
  print('#1');
  thing.foo();
}

Обратите внимание, что синглтон не создается до тех пор, пока геттер не будет вызван в первый раз из-за отложенной инициализации Dart.

Если вы предпочитаете, вы также можете реализовать синглтоны в качестве статического геттера для синглтон-класса. то есть Thing.singleton, а не добытчик верхнего уровня.

Также прочитайте, как Боб Нистром рассказывает о синглетонах из его книги по шаблонам программирования игр.

Ответ 4

Как просто использовать глобальную переменную в вашей библиотеке, например?

single.dart:

library singleton;

var Singleton = new Impl();

class Impl {
  int i;
}

main.dart:

import 'single.dart';

void main() {
  var a = Singleton;
  var b = Singleton;
  a.i = 2;
  print(b.i);
}

Или это нахмурилось?

Синтаксический шаблон необходим в Java, где понятие глобалов не существует, но похоже, что вам не нужно далеко ходить в Дарте.

Ответ 5

Дарт-синглтон конструктором const и factory

class Singleton {
  factory Singleton() =>
    const Singleton._internal_();
  const Singleton._internal_();
}


void main() {
  print(new Singleton() == new Singleton());
  print(identical(new Singleton() , new Singleton()));
}

Ответ 6

Вот еще один возможный способ:

void main() {
  var s1 = Singleton.instance;
  s1.somedata = 123;
  var s2 = Singleton.instance;
  print(s2.somedata); // 123
  print(identical(s1, s2));  // true
  print(s1 == s2); // true
  //var s3 = new Singleton(); //produces a warning re missing default constructor and breaks on execution
}

class Singleton {
  static final Singleton _singleton = new Singleton._internal();
  Singleton._internal();
  static Singleton get instance => _singleton;
  var somedata;
}

Ответ 7

Модифицированный ответ @Seth Ladd для тех, кто предпочитает стиль синглтона Swift, например .shared:

class Auth {
  // singleton
  static final Auth _singleton = Auth._internal();
  factory Auth() => _singleton;
  Auth._internal();
  static Auth get shared => _singleton;

  // variables
  String username;
  String password;
}

Образец:

Auth.shared.username = 'abc';

Ответ 8

Вот краткий пример, который объединяет другие решения. Доступ к синглтону может быть сделан:

  • Использование singleton глобальной переменной, которая указывает на экземпляр.
  • Общий шаблон Singleton.instance.
  • Использование конструктора по умолчанию, который является фабрикой, которая возвращает экземпляр.

Примечание. Необходимо реализовать только один из трех вариантов, чтобы код, использующий одиночный код, был согласованным.

Singleton get singleton => Singleton.instance;
ComplexSingleton get complexSingleton => ComplexSingleton._instance;

class Singleton {
  static final Singleton instance = Singleton._private();
  Singleton._private();
  factory Singleton() => instance;
}

class ComplexSingleton {
  static ComplexSingleton _instance;
  static ComplexSingleton get instance => _instance;
  static void init(arg) => _instance ??= ComplexSingleton._init(arg);

  final property;
  ComplexSingleton._init(this.property);
  factory ComplexSingleton() => _instance;
}

Если вам нужно выполнить сложную инициализацию, вам просто нужно сделать это, прежде чем использовать экземпляр позже в программе.

пример

void main() {
  print(identical(singleton, Singleton.instance));        // true
  print(identical(singleton, Singleton()));               // true
  print(complexSingleton == null);                        // true
  ComplexSingleton.init(0); 
  print(complexSingleton == null);                        // false
  print(identical(complexSingleton, ComplexSingleton())); // true
}

Ответ 9

Синглтон, который не может изменить объект после экземпляра

class User {
  final int age;
  final String name;

  User({
    this.name,
    this.age
    });

  static User _instance;

  static User getInstance({name, age}) {
     if(_instance == null) {
       _instance = User(name: name, idade: age);
       return _instance;
     }
    return _instance;
  }
}

  print(User.getInstance(name: "baidu", age: 24).age); //24

  print(User.getInstance(name: "baidu 2").name); // is not changed //baidu

  print(User.getInstance()); // {name: "baidu": age 24}

Ответ 10

Это должно работать.

class GlobalStore {
    static GlobalStore _instance;
    static GlobalStore get instance {
       if(_instance == null)
           _instance = new GlobalStore()._();
       return _instance;
    }

    _(){

    }
    factory GlobalStore()=> instance;


}

Ответ 11

Поскольку я не очень люблю использовать new ключевое слово или другой конструктор, такой как вызовы для синглетонов, я бы предпочел использовать статический геттер с именем inst например:

// the singleton class
class Dao {
    // singleton boilerplate
        Dao._internal() {}
        static final Dao _singleton = new Dao._internal();
        static get inst => _singleton;

    // business logic
        void greet() => print("Hello from singleton");
}

пример использования:

Dao.inst.greet();       // call a method

// Dao x = new Dao();   // compiler error: Method not found: 'Dao'

// verify that there only exists one and only one instance
assert(identical(Dao.inst, Dao.inst));

Ответ 12

Привет, как насчет этого? Очень простая реализация, сам Injector является синглтоном и также добавляет в него классы. Конечно, может быть продлен очень легко. Если вы ищете что-то более сложное, проверьте этот пакет: https://pub.dartlang.org/packages/flutter_simple_dependency_injection

void main() {  
  Injector injector = Injector();
  injector.add(() => Person('Filip'));
  injector.add(() => City('New York'));

  Person person =  injector.get<Person>(); 
  City city =  injector.get<City>();

  print(person.name);
  print(city.name);
}

class Person {
  String name;

  Person(this.name);
}

class City {
  String name;

  City(this.name);
}


typedef T CreateInstanceFn<T>();

class Injector {
  static final Injector _singleton =  Injector._internal();
  final _factories = Map<String, dynamic>();

  factory Injector() {
    return _singleton;
  }

  Injector._internal();

  String _generateKey<T>(T type) {
    return '${type.toString()}_instance';
  }

  void add<T>(CreateInstanceFn<T> createInstance) {
    final typeKey = _generateKey(T);
    _factories[typeKey] = createInstance();
  }

  T get<T>() {
    final typeKey = _generateKey(T);
    T instance = _factories[typeKey];
    if (instance == null) {
      print('Cannot find instance for type $typeKey');
    }

    return instance;
  }
}