373

シングルトンパターンにより、クラスのインスタンスが1つだけ作成されます。これをDartで構築するにはどうすればよいですか?

4

23 に答える 23

549

Dartのファクトリコンストラクターのおかげで、シングルトンを簡単に構築できます。

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

  factory Singleton() {
    return _singleton;
  }

  Singleton._internal();
}

あなたはそれをこのように構築することができます

main() {
  var s1 = Singleton();
  var s2 = Singleton();
  print(identical(s1, s2));  // true
  print(s1 == s2);           // true
}
于 2012-09-29T02:59:51.820 に答える
417

これは、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 => _instance;
  
}

3.静的フィールド

class SingletonThree {

  SingletonThree._privateConstructor();

  static final SingletonThree instance = SingletonThree._privateConstructor();
  
}

インスタンス化する方法

上記のシングルトンは次のようにインスタンス化されます。

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

ノート:

私はもともとこれを質問として尋ねましたが、上記のすべての方法が有効であり、選択は個人の好みに大きく依存することを発見しました。

于 2019-03-26T00:25:07.260 に答える
49

私はそれが非常に直感的な読書だとは思いませんnew Singleton()。ドキュメントを読んで、new通常のように実際に新しいインスタンスが作成されていないことを確認する必要があります。

シングルトンを行う別の方法があります(基本的にアンドリューが上で言ったこと)。

lib / things.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();
}

シングルトンは、ダートの遅延初期化のためにゲッターが最初に呼び出されるまで作成されないことに注意してください。

必要に応じて、シングルトンクラスに静的ゲッターとしてシングルトンを実装することもできます。つまりThing.singleton、トップレベルのゲッターの代わりに。

また、彼のゲームプログラミングパターンの本からボブナイストロームのシングルトンの見解を読んでください。

于 2013-12-12T23:00:49.867 に答える
42

簡単な答えは次のとおりです。

まず、クラスタイプのprivateとプロパティが必要です。static

次に、privateクラスの外部からのオブジェクトの初期化を防ぎたいので、コンストラクターはである必要があります。

最後に、インスタンスのnull可能性を確認します。nullの場合はインスタンス化して返します。それ以外の場合は、すでにインスタンス化されているインスタンスを返します。

遅延読み込みを使用した実装

class Singleton {
  static Singleton? _instance;

  Singleton._();

  static Singleton get instance => _instance ??= Singleton._();

  void someMethod(){
    ...
  }

  ...
}

積極的な読み込みを使用した実装

class Singleton {
  static Singleton _instance = Singleton._();

  Singleton._();

  static Singleton get instance => _instance;

  void someMethod(){
    ...
  }

  ...
}

使用法

Singleton.instance.someMethod();
于 2019-11-25T06:22:15.063 に答える
25

ライブラリ内でグローバル変数を使用するのはどうですか?

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ではシングルトンパターンが必要ですが、Dartでは長い道のりを歩む必要はないようです。

于 2012-09-29T03:41:48.970 に答える
21

別の可能な方法は次のとおりです。

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;
}
于 2014-09-25T17:35:08.743 に答える
14

constコンストラクターとファクトリーによるDartシングルトン

class Singleton {
  factory Singleton() =>
    Singleton._internal_();
  Singleton._internal_();
}
 
 
void main() {
  print(new Singleton() == new Singleton());
  print(identical(new Singleton() , new Singleton()));
}
于 2013-12-20T13:00:30.387 に答える
12

インスタンス化後にオブジェクトを変更できないシングルトン

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, age: 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}
于 2019-06-22T20:10:37.333 に答える
12

この例では、シングルトンを使用したいときにも必要な他のことを行います。例えば:

  • シングルトンのコンストラクターに値を渡します
  • コンストラクター自体の内部で値を初期化します
  • シングルトンの変数に値を設定します
  • これらの値にアクセスおよびアクセスできる

このような:

class MySingleton {

  static final MySingleton _singleton = MySingleton._internal();

  String _valueToBeSet;
  String _valueAlreadyInSingleton;
  String _passedValueInContructor;

  get getValueToBeSet => _valueToBeSet;

  get getValueAlreadyInSingleton => _valueAlreadyInSingleton;

  get getPassedValueInConstructor => _passedValueInContructor;

  void setValue(newValue) {
    _valueToBeSet = newValue;
  }

  factory MySingleton(String passedString) {
    _singleton._valueAlreadyInSingleton = "foo";
    _singleton._passedValueInContructor = passedString;

    return _singleton;
  }

  MySingleton._internal();
}

MySingletonの使用法:

void main() {

MySingleton mySingleton =  MySingleton("passedString");
mySingleton.setValue("setValue");
print(mySingleton.getPassedValueInConstructor);
print(mySingleton.getValueToBeSet);
print(mySingleton.getValueAlreadyInSingleton);

}
于 2021-02-26T20:33:54.457 に答える
8

すべての選択肢を読んだ後、私はこれを思いつきました。これは「クラシックシングルトン」を思い出させます。

class AccountService {
  static final _instance = AccountService._internal();

  AccountService._internal();

  static AccountService getInstance() {
    return _instance;
  }
}
于 2019-10-24T09:33:57.447 に答える
8

バージョン以来、キーワードDart 2.13でとても簡単です。キーワードを使用すると、オブジェクトを遅延インスタンス化できます。lateLate

例として、あなたはそれを見ることができます:

class LazySingletonExample {
  LazySingletonExample._() {
    print('instance created.');
  }

  static late final LazySingletonExample instance = LazySingletonExample._();
  
  
}

instance注:レイジーフィールドを呼び出すと、インスタンス化されるのは1回だけであることに注意してください。

于 2021-05-22T19:53:57.540 に答える
7

これは、他のソリューションを組み合わせた簡潔な例です。シングルトンへのアクセスは、次の方法で実行できます。

  • singletonインスタンスを指すグローバル変数を使用します。
  • 一般的なSingleton.instanceパターン。
  • インスタンスを返すファクトリであるデフォルトのコンストラクタを使用します。

注:シングルトンを使用するコードに一貫性を持たせるために、3つのオプションのうち1つだけを実装する必要があります。

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
}
于 2018-06-25T20:45:20.870 に答える
7

次のようなシングルトンのSwiftスタイルを好む人のために@SethLaddの回答を変更しました.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';
于 2019-01-13T08:18:45.697 に答える
7

これが私のプロジェクトにシングルトンを実装する方法です

フラッターファイアベースからインスピレーションを受けた=>FirebaseFirestore.instance.collection('collectionName')

class FooAPI {
  foo() {
    // some async func to api
  }
}

class SingletonService {
  FooAPI _fooAPI;

  static final SingletonService _instance = SingletonService._internal();

  static SingletonService instance = SingletonService();

  factory SingletonService() {
    return _instance;
  }

  SingletonService._internal() {
    // TODO: add init logic if needed
    // FOR EXAMPLE API parameters
  }

  void foo() async {
    await _fooAPI.foo();
  }
}

void main(){
  SingletonService.instance.foo();
}

私のプロジェクトの例

class FirebaseLessonRepository implements LessonRepository {
  FirebaseLessonRepository._internal();

  static final _instance = FirebaseLessonRepository._internal();

  static final instance = FirebaseLessonRepository();

  factory FirebaseLessonRepository() => _instance;

  var lessonsCollection = fb.firestore().collection('lessons');
  
  // ... other code for crud etc ...
}

// then in my widgets
FirebaseLessonRepository.instance.someMethod(someParams);
于 2020-07-28T07:29:23.633 に答える
6

状態管理にFlutterとproviderパッケージを使用している場合、シングルトンの作成と使用は非常に簡単です。

  1. インスタンスを作成する
  void main() {
      runApp(
        MultiProvider(
          providers: [
            ChangeNotifierProvider(create: (context) => SomeModel()),
            Provider(create: (context) => SomeClassToBeUsedAsSingleton()),
          ],
          child: MyApp(),
        ),
      );
    }
  1. インスタンスを取得する
Widget build(BuildContext context) { 
  var instance = Provider.of<SomeClassToBeUsedAsSingleton>(context); 
  ...
于 2021-02-28T21:35:52.663 に答える
3

これは機能するはずです。

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

    _(){

    }
    factory GlobalStore()=> instance;


}
于 2018-10-13T08:31:58.680 に答える
3

キーワードやシングルトンの呼び出しのような他のコンストラクターを使用するのはあまり好きではないので、たとえば次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));
于 2018-12-13T16:33:25.140 に答える
3

こんにちは、このようなものはどうですか?非常に単純な実装であり、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;
  }
}
于 2019-05-09T21:56:41.647 に答える
3

** Dart SoundNullSafetyのSigletonパラダイム**

このコードスニペットは、dartにシングルトンを実装する方法を示しています。これは、たとえば、クラスの同じオブジェクトを毎回使用する必要がある状況で一般的に使用されます。データベーストランザクションで。

class MySingleton {
  static MySingleton? _instance;
  MySingleton._internal();
  factory MySingleton() {
    if (_instance == null) {
      _instance = MySingleton._internal();
    }
     return _instance!;
  }
}
于 2021-07-28T14:40:37.207 に答える
1

私はこの単純なパターンをダーツと以前はSwiftで使用しました。私はそれが簡潔であり、それを使用する唯一の方法であることが好きです。

class Singleton {
  static Singleton shared = Singleton._init();
  Singleton._init() {
    // init work here
  }

  void doSomething() {
  }
}

Singleton.shared.doSomething();
于 2021-01-23T03:35:23.080 に答える
1

これは、シングルトンクラスを作成する方法でもあります

class Singleton{
  Singleton._();
  static final Singleton db = Singleton._();
}
于 2021-02-02T19:38:28.020 に答える
1

Singletonnullの安全演算子とファクトリコンストラクタを使用すると、オブジェクトをより適切に作成できます。

class Singleton {
  static Singleton? _instance;

  Singleton._internal();

  factory Singleton() => _instance ??= Singleton._internal();
  
  void someMethod() {
    print("someMethod Called");
  }
}

使用法:

void main() {
  Singleton object = Singleton();
  object.someMethod(); /// Output: someMethod Called
}

注: ??はNull対応の演算子です。左側の値がnullの場合、右側の値を返します。つまり、この例_instance ?? Singleton._internal();Singleton._internal()は、オブジェクトが呼び出されたときに最初に返され、rest_instanceが返されます。

于 2021-09-29T10:29:28.927 に答える
-1

Constantコンストラクターを使用できます。

class Singleton {
  const Singleton(); //Constant constructor
  
  void hello() { print('Hello world'); }
}

例:

Singleton s = const Singleton();
s.hello(); //Hello world

ドキュメントによると:

定数コンストラクター

クラスが変更されないオブジェクトを生成する場合は、これらのオブジェクトをコンパイル時定数にすることができます。これを行うには、constコンストラクターを定義し、すべてのインスタンス変数がfinalであることを確認します。

于 2021-07-13T13:45:13.090 に答える