সিঙ্গেলটন প্যাটার্নটি নিশ্চিত করে যে কোনও শ্রেণীর তৈরি হওয়া কেবলমাত্র একটি উদাহরণ instance আমি এটি ডার্টে কীভাবে তৈরি করব?
সিঙ্গেলটন প্যাটার্নটি নিশ্চিত করে যে কোনও শ্রেণীর তৈরি হওয়া কেবলমাত্র একটি উদাহরণ instance আমি এটি ডার্টে কীভাবে তৈরি করব?
উত্তর:
ডার্টের কারখানার নির্মাণকারীদের ধন্যবাদ , একটি সিঙ্গলটন তৈরি করা সহজ:
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
}
new
অর্থ এখানে "একটি নতুন নির্মাণ করুন" নয়, এটি কেবল "কনস্ট্রাক্টর চালান" বলে।
new
শব্দ দাড়ায় যে বর্গ instantiated করা হয়, যা এটা হয় না। আমি একটি স্থির পদ্ধতিতে যেতে চাই get()
বা getInstance()
জাভাতে যেমন করি।
Singleton._internal();
যা কোনও পদ্ধতি কল হিসাবে দেখা যায় যখন এটি সত্যিই নির্মাতার সংজ্ঞা হয়। আছে _internal
নাম। এবং নিফটি ভাষার নকশা বিন্দুটি রয়েছে যে ডার্ট আপনাকে একটি সাধারণ নির্মাণকারী ব্যবহার করে শুরু করতে (ডার্ট আউট?) দেয় এবং তারপরে, প্রয়োজনে, factory
সমস্ত কলার পরিবর্তন না করে এটিকে কোনও পদ্ধতিতে পরিবর্তন করতে দেয়।
এখানে ডার্টে সিঙ্গলটন তৈরির বিভিন্ন উপায়ের একটি তুলনা করা হয়েছে।
class SingletonOne {
SingletonOne._privateConstructor();
static final SingletonOne _instance = SingletonOne._privateConstructor();
factory SingletonOne() {
return _instance;
}
}
class SingletonTwo {
SingletonTwo._privateConstructor();
static final SingletonTwo _instance = SingletonTwo._privateConstructor();
static SingletonTwo get instance => _instance;
}
class SingletonThree {
SingletonThree._privateConstructor();
static final SingletonThree instance = SingletonThree._privateConstructor();
}
উপরের সিলেটলেটগুলি এভাবে ইনস্ট্যান্ট করা হয়:
SingletonOne one = SingletonOne();
SingletonTwo two = SingletonTwo.instance;
SingletonThree three = SingletonThree.instance;
বিঃদ্রঃ:
আমি প্রথমে এটি একটি প্রশ্ন হিসাবে জিজ্ঞাসা করেছি , কিন্তু আবিষ্কার করেছি যে উপরের সমস্ত পদ্ধতি বৈধ এবং পছন্দটি মূলত ব্যক্তিগত পছন্দকে নির্ভর করে।
static final SingletonThree instance = SingletonThree()
। একই জন্য দ্বিতীয় পথে যায় _instance
। আমি জানি না যে প্রাইভেট কনস্ট্রাক্টর ব্যবহার না করার অসুবিধা কী। এখনও পর্যন্ত, আমি আমার পথে কোনও সমস্যা পাই না। দ্বিতীয় এবং তৃতীয় উপায়গুলি যে কোনও উপায়ে ডিফল্ট কনস্ট্রাক্টরে কলটিকে ব্লক করছে না।
SingletonThree instance2 = SingletonThree()
। কোনও প্রাইভেট কনস্ট্রাক্টর যখন আপনি এটি করার চেষ্টা করেন, আপনি ত্রুটি পাবেন:The class 'SingletonThree' doesn't have a default constructor.
আমি এটি খুব স্বজ্ঞাত পড়া খুঁজে পাই না 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
শীর্ষ স্তরের প্রাপ্তির পরিবর্তে।
এছাড়াও তার গেম প্রোগ্রামিং নিদর্শন বই থেকে বব নাইস্ট্রমের সিলেটলেটগুলি পড়ুন ।
আপনার লাইব্রেরির মধ্যে কেবলমাত্র বৈশ্বিক পরিবর্তনশীল ব্যবহারের বিষয়ে কী?
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);
}
নাকি এটিকে ভ্রান্ত করা হচ্ছে?
জাভাতে সিঙ্গলটন প্যাটার্ন প্রয়োজনীয় যেখানে গ্লোবালগুলির ধারণার অস্তিত্ব নেই, তবে মনে হচ্ছে আপনার ডার্টে আরও দীর্ঘ পথের প্রয়োজন হবে না।
Singleton
অ্যাক্সেস করা সহজ করার জন্য তিনি সঠিকভাবে একটি শীর্ষ-স্তরের ভেরিয়েবল ব্যবহার করেছিলেন। আমার উপরের উদাহরণে, Singleton
ক্লাসটি একটি আসল সিঙ্গলটন, কেবলমাত্র এক উদাহরণ হ'ল Singleton
বিচ্ছিন্নতায় থাকতে পারে।
new Singleton._internal()
অনেকগুলি অবজেক্ট তৈরি করে যতবার ইচ্ছা কল করতে পারে Singleton
। তাহলে Impl
এন্ড্রুর উদাহরণে বর্গ ব্যক্তিগত ছিল ( _Impl
), এটি আপনার উদাহরণ হিসাবে একই হতে হবে। অন্যদিকে, সিঙ্গেলটন হ'ল একটি অ্যান্টিপ্যাটার্ন এবং কোনওভাবেই এটি ব্যবহার করা উচিত নয়।
Singelton._internal()
। আপনি যুক্তি দিতে পারেন যে সিনগেলটন শ্রেণির বিকাশকারীরা ক্লাসটি বেশ কয়েকবার তাত্পর্যপূর্ণ করতে পারে। অবশ্যই এনাম সিঙ্গেলটন আছে তবে আমার কাছে এটি কেবল তাত্ত্বিক ব্যবহার। একটি এনাম একটি এনাম, কোনও সিনজেলটন নয় ... শীর্ষ স্তরের ভেরিয়েবলগুলি (@ অ্যান্ড্রু এবং @ সেথ) ব্যবহারের জন্য: কেউ কি শীর্ষ স্তরের ভেরিয়েবল লিখতে পারেন না? এটি কোনওভাবেই সুরক্ষিত নয়, বা আমি কিছু মিস করছি?
এখানে আরও একটি সম্ভাব্য উপায়:
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;
}
সিঙ্গলটন যা উদাহরণের পরে অবজেক্টটি পরিবর্তন করতে পারে না
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}
কারা সিঙ্গলটনের মতো সুইফ্ট স্টাইল পছন্দ করে তার জন্য পরিবর্তিত @ শেঠ লেড উত্তর .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';
সমস্ত বিকল্পগুলি পড়ার পরে আমি এটি নিয়ে এসেছি, যা আমাকে "ক্লাসিক সিঙ্গলটন" মনে করিয়ে দেয়:
class AccountService {
static final _instance = AccountService._internal();
AccountService._internal();
static AccountService getInstance() {
return _instance;
}
}
getInstance
পদ্ধতি পরিবর্তন করতে হবে instance
:static AccountService get instance => _instance;
এখানে একটি সংক্ষিপ্ত উদাহরণ যা অন্যান্য সমাধানগুলিকে একত্র করে। একক অ্যাক্সেস দ্বারা সম্পন্ন করা যেতে পারে:
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
}
হ্যালো এই জাতীয় কিছু সম্পর্কে কি? খুব সাধারণ বাস্তবায়ন, ইনজেক্টর নিজেই সিঙ্গলটন এবং এতে ক্লাস যুক্ত করেছে। অবশ্যই খুব সহজেই বাড়ানো যেতে পারে। আপনি যদি আরও পরিশীলিত কিছু খুঁজছেন তবে এই প্যাকেজটি দেখুন: 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;
}
}
এই কাজ করা উচিত.
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._();
করতে হবে. কী _(){}
করার কথা? এটি নিরর্থক বলে মনে হচ্ছে।
যেহেতু আমি 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));