আপনি কীভাবে ডার্টে একটি সিঙ্গলটন তৈরি করবেন?


203

সিঙ্গেলটন প্যাটার্নটি নিশ্চিত করে যে কোনও শ্রেণীর তৈরি হওয়া কেবলমাত্র একটি উদাহরণ instance আমি এটি ডার্টে কীভাবে তৈরি করব?


আমি নীচে বেশ কয়েকটি উত্তর দেখেছি যা ক্লাস সিঙ্গলটন তৈরির বিভিন্ন উপায় বর্ণনা করে। সুতরাং আমি কেন এই শ্রেণী_নাম অবজেক্টটি পছন্দ করি না তা নিয়ে আমি ভাবছি; if (অবজেক্ট == নাল) রিটার্ন অবজেক্ট = নতুন ক্লাস_নাম; অন্যথায় বস্তুটি
ফেরান

উত্তর:


321

ডার্টের কারখানার নির্মাণকারীদের ধন্যবাদ , একটি সিঙ্গলটন তৈরি করা সহজ:

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
}

2
যদিও এটি দু'বার ইনস্ট্যান্ট করার কী লাভ? আপনি যখন দ্বিতীয়বার এটি ইনস্ট্যান্ট করবেন তখন কি এটির ত্রুটি ছুঁড়ে ফেলা উচিত নয়?
ওয়েস্টোকে

53
আমি এটি দু'বার ইনস্ট্যান্ট করছি না, কেবলমাত্র দু'বার সিঙ্গেলটন অবজেক্টের রেফারেন্স পাচ্ছি। আপনি সম্ভবত এটি বাস্তব জীবনে পরপর দু'বার করবেন না :) আমি ব্যতিক্রম ছুঁড়ে ফেলতে চাই না, প্রতিবারই "নতুন সিঙ্গেলটন ()" বলার সময় আমি একই সিঙ্গলটন উদাহরণ চাই। আমি স্বীকার করি, এটি কিছুটা বিভ্রান্তিকর ... এর newঅর্থ এখানে "একটি নতুন নির্মাণ করুন" নয়, এটি কেবল "কনস্ট্রাক্টর চালান" বলে।
শেঠ লেড

1
কারখানার কীওয়ার্ডটি এখানে কী সরবরাহ করে? এটি বিশুদ্ধরূপে বাস্তবায়নটি বর্ণনা করছে। কেন এটি প্রয়োজন?
ικrτhικ

4
এটি ধরণের বিভ্রান্তিকর যে আপনি উদাহরণটি পেতে কোনও কনস্ট্রাক্টর ব্যবহার করছেন। newশব্দ দাড়ায় যে বর্গ instantiated করা হয়, যা এটা হয় না। আমি একটি স্থির পদ্ধতিতে যেতে চাই get()বা getInstance()জাভাতে যেমন করি।
স্টিভেন রুজ

11
@ শেঠল্যাড এটি খুব সুন্দর তবে আমি পরামর্শ দিচ্ছি যে এর কয়েকটি পয়েন্ট ব্যাখ্যা করতে হবে needs এমন একটি অদ্ভুত বাক্য গঠন রয়েছে Singleton._internal();যা কোনও পদ্ধতি কল হিসাবে দেখা যায় যখন এটি সত্যিই নির্মাতার সংজ্ঞা হয়। আছে _internalনাম। এবং নিফটি ভাষার নকশা বিন্দুটি রয়েছে যে ডার্ট আপনাকে একটি সাধারণ নির্মাণকারী ব্যবহার করে শুরু করতে (ডার্ট আউট?) দেয় এবং তারপরে, প্রয়োজনে, factoryসমস্ত কলার পরিবর্তন না করে এটিকে কোনও পদ্ধতিতে পরিবর্তন করতে দেয়।
জেরি 101

169

এখানে ডার্টে সিঙ্গলটন তৈরির বিভিন্ন উপায়ের একটি তুলনা করা হয়েছে।

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;

বিঃদ্রঃ:

আমি প্রথমে এটি একটি প্রশ্ন হিসাবে জিজ্ঞাসা করেছি , কিন্তু আবিষ্কার করেছি যে উপরের সমস্ত পদ্ধতি বৈধ এবং পছন্দটি মূলত ব্যক্তিগত পছন্দকে নির্ভর করে।


3
আমি শুধু আপনার উত্তর upvated। গৃহীত উত্তরের চেয়ে অনেক বেশি স্পষ্ট। আরও একটি প্রশ্ন: দ্বিতীয় এবং তৃতীয় উপায়ে, ব্যক্তিগত নির্মাণকারীর বিন্দুটি কী? আমি দেখেছি অনেক লোক তা করেছে তবে আমি বিষয়টি বুঝতে পারি না। আমি সবসময় সহজভাবে ব্যবহার করি static final SingletonThree instance = SingletonThree()। একই জন্য দ্বিতীয় পথে যায় _instance। আমি জানি না যে প্রাইভেট কনস্ট্রাক্টর ব্যবহার না করার অসুবিধা কী। এখনও পর্যন্ত, আমি আমার পথে কোনও সমস্যা পাই না। দ্বিতীয় এবং তৃতীয় উপায়গুলি যে কোনও উপায়ে ডিফল্ট কনস্ট্রাক্টরে কলটিকে ব্লক করছে না।
sgon00

3
@ sgon00, প্রাইভেট কনস্ট্রাক্টরটি যাতে আপনি অন্য কোনও উদাহরণ তৈরি করতে না পারেন। অন্যথায় কেউ করতে পারে SingletonThree instance2 = SingletonThree()। কোনও প্রাইভেট কনস্ট্রাক্টর যখন আপনি এটি করার চেষ্টা করেন, আপনি ত্রুটি পাবেন:The class 'SingletonThree' doesn't have a default constructor.
সুরগাচ

40

আমি এটি খুব স্বজ্ঞাত পড়া খুঁজে পাই না new Singleton()। আপনাকে সাধারণত ডকসগুলি পড়তে হবে যা newআসলে কোনও নতুন উদাহরণ তৈরি করে না, যেমনটি সাধারণত হয়।

এখানে সিলেটলেটগুলি করার আরও একটি উপায় রয়েছে (মূলত উপরে অ্যান্ড্রু যা বলেছিল)।

lib / অনুপস্থিত 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();
}

মনে রাখবেন যে ডার্টের অলস সূচনালগ্নের কারণে প্রথমবার গ্রাহককে ডাকা না হওয়া পর্যন্ত সিঙ্গলটন তৈরি হয় না।

আপনি যদি পছন্দ করেন তবে আপনি সিঙ্গলটন ক্লাসে স্ট্যাটিক গেটার হিসাবে সিলেটলেটগুলি প্রয়োগ করতে পারেন। অর্থাত্ Thing.singletonশীর্ষ স্তরের প্রাপ্তির পরিবর্তে।

এছাড়াও তার গেম প্রোগ্রামিং নিদর্শন বই থেকে বব নাইস্ট্রমের সিলেটলেটগুলি পড়ুন ।


1
গ্রেগ এবং ডার্টের শীর্ষ-স্তরের সম্পত্তির বৈশিষ্ট্যটির জন্য এটি আমার কাছে আরও অর্থবোধ করে।
सन পিআই

এটি কোন মূর্খতা নয়। ভাষায় একটি সিঙ্গলটন প্যাটার্ন তৈরি করা একটি স্বপ্নের বৈশিষ্ট্য এবং আপনি এটি ব্যবহার করছেন না কারণ আপনি এটি ব্যবহার করছেন না।
আরশ

1
শেঠের উদাহরণ এবং এই উদাহরণ দুটিই সিঙ্গলটন নিদর্শন। এটি সত্যই সিনট্যাক্সের প্রশ্ন "নতুন সিঙ্গেলটন ()" বনাম "সিঙ্গেলটন"। আমি আরও স্পষ্ট মনে করি। ডার্টের কারখানার নির্মাতারা কার্যকর, তবে আমি মনে করি না এটি তাদের পক্ষে ভাল ব্যবহারের ক্ষেত্রে। আমি আরও মনে করি ডার্টের অলস সূচনাটি একটি দুর্দান্ত বৈশিষ্ট্য, যা ব্যবহার করা হয়নি। উপরের ববের নিবন্ধটিও পড়ুন - তিনি বেশিরভাগ ক্ষেত্রে সিঙ্গলেটনের বিরুদ্ধে প্রস্তাব দেন।
গ্রেগ লো

আমি এই থ্রেডটি মেলিং তালিকায় পড়ারও পরামর্শ দিচ্ছি। groups.google.com/a/dartlang.org/d/msg/misc/9dFunchCT4kA/…
গ্রেগ লো

এটি উপায় ভাল। "নতুন" কীওয়ার্ডটি বেশ ভারীভাবে একটি নতুন অবজেক্টের নির্মাণকে বোঝায়। গৃহীত সমাধানটি সত্যই ভুল অনুভব করে।
সাভা বি।

16

আপনার লাইব্রেরির মধ্যে কেবলমাত্র বৈশ্বিক পরিবর্তনশীল ব্যবহারের বিষয়ে কী?

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);
}

নাকি এটিকে ভ্রান্ত করা হচ্ছে?

জাভাতে সিঙ্গলটন প্যাটার্ন প্রয়োজনীয় যেখানে গ্লোবালগুলির ধারণার অস্তিত্ব নেই, তবে মনে হচ্ছে আপনার ডার্টে আরও দীর্ঘ পথের প্রয়োজন হবে না।


5
শীর্ষ স্তরের ভেরিয়েবলগুলি দুর্দান্ত। তবে যে কেউ সিঙ্গল.ডার্ট আমদানি করতে পারে সে "নতুন ইমপ্ল ()" নির্মান করতে বিনামূল্যে। আপনি ইমপ্লিকে আন্ডারস্কোর কনস্ট্রাক্টর দিতে পারেন তবে সিঙ্গলটন লাইব্রেরির ভিতরে কোডটি সেই কনস্ট্রাক্টরকে কল করতে পারে।
শেঠ লাড

এবং আপনার প্রয়োগের কোডটি কি পারবে না? আপনি নিজের উত্তরে ব্যাখ্যা করতে পারেন কেন এটি শীর্ষ স্তরের ভেরিয়েবলের চেয়ে ভাল?
জানুয়ারী

2
হাই @ জান, এটি আরও ভাল বা খারাপ নয়, এটি অন্যরকম। অ্যান্ড্রু-র উদাহরণে ইমপ্ল কোনও সিঙ্গলটন শ্রেণি নয়। উদাহরণটি Singletonঅ্যাক্সেস করা সহজ করার জন্য তিনি সঠিকভাবে একটি শীর্ষ-স্তরের ভেরিয়েবল ব্যবহার করেছিলেন। আমার উপরের উদাহরণে, Singletonক্লাসটি একটি আসল সিঙ্গলটন, কেবলমাত্র এক উদাহরণ হ'ল Singletonবিচ্ছিন্নতায় থাকতে পারে।
শেঠ লাড

1
শেঠ, আপনি ঠিক না। নেই কোন হিসাবে সেখানে ক্লাসের instantiability সীমাবদ্ধ কোন উপায় নেই, ডার্ট উপায় একটি সত্য Singleton গড়ে তুলতে ভিতরে প্রকাশক গ্রন্থাগার। এটি সর্বদা গ্রন্থাগারের লেখকের কাছ থেকে শৃঙ্খলার প্রয়োজন। আপনার উদাহরণে, ঘোষিত গ্রন্থাগারটি ক্লাসের new Singleton._internal()অনেকগুলি অবজেক্ট তৈরি করে যতবার ইচ্ছা কল করতে পারে Singleton। তাহলে Implএন্ড্রুর উদাহরণে বর্গ ব্যক্তিগত ছিল ( _Impl), এটি আপনার উদাহরণ হিসাবে একই হতে হবে। অন্যদিকে, সিঙ্গেলটন হ'ল একটি অ্যান্টিপ্যাটার্ন এবং কোনওভাবেই এটি ব্যবহার করা উচিত নয়।
লাডিসেক

@ লাডিসেক, আপনি কোনও লাইব্রেরির বিকাশকারীকে নতুন কল না করার বিষয়ে বিশ্বাস করবেন না Singelton._internal()। আপনি যুক্তি দিতে পারেন যে সিনগেলটন শ্রেণির বিকাশকারীরা ক্লাসটি বেশ কয়েকবার তাত্পর্যপূর্ণ করতে পারে। অবশ্যই এনাম সিঙ্গেলটন আছে তবে আমার কাছে এটি কেবল তাত্ত্বিক ব্যবহার। একটি এনাম একটি এনাম, কোনও সিনজেলটন নয় ... শীর্ষ স্তরের ভেরিয়েবলগুলি (@ অ্যান্ড্রু এবং @ সেথ) ব্যবহারের জন্য: কেউ কি শীর্ষ স্তরের ভেরিয়েবল লিখতে পারেন না? এটি কোনওভাবেই সুরক্ষিত নয়, বা আমি কিছু মিস করছি?
টোবিয়াস রিটজউ

12

এখানে আরও একটি সম্ভাব্য উপায়:

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;
}

11

কনস্ট্রাক্টর এবং ফ্যাক্টরি দ্বারা ডার্ট সিঙ্গলটন

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


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

5

সিঙ্গলটন যা উদাহরণের পরে অবজেক্টটি পরিবর্তন করতে পারে না

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}

4

কারা সিঙ্গলটনের মতো সুইফ্ট স্টাইল পছন্দ করে তার জন্য পরিবর্তিত @ শেঠ লেড উত্তর .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';

4

সমস্ত বিকল্পগুলি পড়ার পরে আমি এটি নিয়ে এসেছি, যা আমাকে "ক্লাসিক সিঙ্গলটন" মনে করিয়ে দেয়:

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

  AccountService._internal();

  static AccountService getInstance() {
    return _instance;
  }
}

3
আমি এই জাতীয় সম্পত্তি হিসাবে getInstanceপদ্ধতি পরিবর্তন করতে হবে instance:static AccountService get instance => _instance;
gianlucaparadise

আমি এটি পছন্দ করি যেহেতু উদাহরণটি ফিরে আসার আগে এবং অন্যান্য পদ্ধতি ব্যবহার করার আগে আমি কিছু যুক্ত করতে চাই।
চিটগোکس

4

এখানে একটি সহজ উত্তর:

class Singleton {
  static Singleton _instance;

  Singleton._();

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

3

এখানে একটি সংক্ষিপ্ত উদাহরণ যা অন্যান্য সমাধানগুলিকে একত্র করে। একক অ্যাক্সেস দ্বারা সম্পন্ন করা যেতে পারে:

  • একটি singletonবৈশ্বিক পরিবর্তনশীল ব্যবহার করে যা উদাহরণটিকে নির্দেশ করে।
  • সাধারণ Singleton.instanceপ্যাটার্ন।
  • ডিফল্ট কনস্ট্রাক্টর ব্যবহার করে, যা একটি ফ্যাক্টরি যা উদাহরণটি দেয় returns

দ্রষ্টব্য: আপনার তিনটি বিকল্পের মধ্যে একটিরই প্রয়োগ করা উচিত যাতে সিঙ্গলটনের সাহায্যে কোডটি সামঞ্জস্য হয়।

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
}

1

হ্যালো এই জাতীয় কিছু সম্পর্কে কি? খুব সাধারণ বাস্তবায়ন, ইনজেক্টর নিজেই সিঙ্গলটন এবং এতে ক্লাস যুক্ত করেছে। অবশ্যই খুব সহজেই বাড়ানো যেতে পারে। আপনি যদি আরও পরিশীলিত কিছু খুঁজছেন তবে এই প্যাকেজটি দেখুন: https://pub.dartlang.org/packages/flutter_simple_d dependency_inication

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;
  }
}

0

এই কাজ করা উচিত.

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

    _(){

    }
    factory GlobalStore()=> instance;


}

উত্তর হিসাবে অনুগামী প্রশ্ন পোস্ট করবেন না। এই কোডটি নিয়ে সমস্যাটি হ'ল এটি কিছুটা ভার্বোস। static GlobalStore get instance => _instance ??= new GlobalStore._();করতে হবে. কী _(){}করার কথা? এটি নিরর্থক বলে মনে হচ্ছে।
গন্টার জ্যাচবাউর

দুঃখিত, এটি একটি পরামর্শ ছিল, একটি ফলোআপ প্রশ্ন নয়, _ () {a একটি প্রাইভেট কনস্ট্রাক্টর তৈরি করবেন?
ভিলসাদ পিপি

নির্মাণকারীরা ক্লাসের নাম দিয়ে শুরু করে। এটি কেবলমাত্র একটি সাধারণ বেসরকারী পদ্ধতি যা কোনও রিটার্নের ধরণ ছাড়াই নির্দিষ্ট করা হয়।
গন্টার জ্যাচবাউর

1
ডাউনভোটের জন্য দুঃখিত, তবে আমি মনে করি এটি নিম্নমানের এবং বিদ্যমান উত্তরগুলি ছাড়াও কোনও মান যুক্ত করে না।
গন্টার জ্যাচবাউর

2
যদিও এই কোডটি প্রশ্নের উত্তর দিতে পারে, কীভাবে এবং / বা কেন এটি সমস্যার সমাধান করে তা সম্পর্কিত অতিরিক্ত প্রসঙ্গ সরবরাহ করলে উত্তরের দীর্ঘমেয়াদী মান উন্নত হবে।
কার্ল রিখটার

0

যেহেতু আমি 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));
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.