मूल बातें 🌟
Singleton पैटर्न का परिचय
कल्पना कीजिए एक ऐसे सुपरहीरो की, जो पूरे ब्रह्मांड में केवल एक बार मौजूद हो सकता है। यही है Singleton पैटर्न! 🦸♂️
एक अनूठे हीरो की जरूरत क्यों? 🤔
कुछ आम परिस्थितियां:
- 🎮 एक वीडियो गेम में कई स्कोरबोर्ड... पूरी अव्यवस्था!
- 🏦 एक ही डेटाबेस के कई कनेक्शन... संसाधनों की बर्बादी!
- ⚙️ कई अलग-अलग कॉन्फ़िगरेशन... अराजकता का द्वार!
Singleton की सुपरपावर्स
- 💪 एकता की शक्ति: एक ही इंस्टेंस, जैसे गोथम सिटी का एक ही बैटमैन
- 🌟 वैश्विक दृष्टि: हर जगह से पहुंच, जैसे आसमान में बैट-सिग्नल
- 🎯 सटीकता: सत्य का एक ही स्रोत, जैसे सॉरन की एक ही अंगूठी
बेसिक इम्प्लीमेंटेशन
हमारे हीरो का कोड
typescript
1class Logger {
2 private static instance: Logger;
3 private logCount: number = 0;
4
5 private constructor() {
6 console.log('🚀 Logger जाग रहा है...');
7 }
8
9 public static getInstance(): Logger {
10 if (!Logger.instance) {
11 Logger.instance = new Logger();
12 }
13 return Logger.instance;
14 }
15
16 public log(message: string): void {
17 this.logCount++;
18 console.log(`📝 [लॉग #${this.logCount}] ${message}`);
19 }
20
21 public getStats(): string {
22 return `📊 कुल लॉग: ${this.logCount}`;
23 }
24}
सरल उपयोग
typescript
1const logger = Logger.getInstance();
2logger.log('हमारा हीरो तैयार है!');
3console.log(logger.getStats());
उन्नत तकनीकें 🚀
थ्रेड-सेफ Singleton
मल्टी-थ्रेड वातावरण में, हमारे हीरो को अतिरिक्त कवच की जरूरत है! यहाँ एक थ्रेड-सेफ कार्यान्वयन है:
typescript
1class ThreadSafeLogger {
2 private static instance: ThreadSafeLogger;
3 private static instanceLock = false;
4 private logs: string[] = [];
5
6 private constructor() {}
7
8 public static getInstance(): ThreadSafeLogger {
9 if (!ThreadSafeLogger.instanceLock) {
10 ThreadSafeLogger.instanceLock = true;
11 if (!ThreadSafeLogger.instance) {
12 ThreadSafeLogger.instance = new ThreadSafeLogger();
13 }
14 ThreadSafeLogger.instanceLock = false;
15 }
16 return ThreadSafeLogger.instance;
17 }
18}
लेजी इनिशियलाइजेशन वाला Singleton 🦥
typescript
1class LazyLogger {
2 private static instance: LazyLogger;
3 private config: object;
4
5 private constructor(config: object) {
6 this.config = config;
7 }
8
9 public static getInstance(config?: object): LazyLogger {
10 if (!LazyLogger.instance && config) {
11 LazyLogger.instance = new LazyLogger(config);
12 }
13 if (!LazyLogger.instance) {
14 throw new Error(
15 'पहली बार इनिशियलाइज करते समय Logger को कॉन्फ़िगरेशन की आवश्यकता है!',
16 );
17 }
18 return LazyLogger.instance;
19 }
20}
टेस्टिंग के लिए रीसेट करने योग्य Singleton 🧪
typescript
1class TestableLogger {
2 private static instance: TestableLogger;
3
4 private constructor() {}
5
6 public static getInstance(): TestableLogger {
7 if (!TestableLogger.instance) {
8 TestableLogger.instance = new TestableLogger();
9 }
10 return TestableLogger.instance;
11 }
12
13 // टेस्टिंग के लिए विशेष मेथड
14 public static resetInstance(): void {
15 TestableLogger.instance = null;
16 }
17}
जेनेरिक Singleton 🎭
typescript
1class GenericSingleton<T> {
2 private static instances: Map<string, any> = new Map();
3
4 protected constructor() {}
5
6 public static getInstance<T>(this: new () => T): T {
7 const className = this.name;
8 if (!GenericSingleton.instances.has(className)) {
9 GenericSingleton.instances.set(className, new this());
10 }
11 return GenericSingleton.instances.get(className);
12 }
13}
14
15// उपयोग
16class UserService extends GenericSingleton<UserService> {
17 public getUsers() {
18 return ['user1', 'user2'];
19 }
20}
21
22class ConfigService extends GenericSingleton<ConfigService> {
23 public getConfig() {
24 return { api: 'url' };
25 }
26}
एंटी-पैटर्न और बचने योग्य जाल ⚠️
- टाइट कपलिंग
typescript
1// बचें ❌
2class BadSingleton {
3 public static getInstance() {
4 // कोड...
5 }
6 public doDirectDatabaseOperation() {
7 // डेटाबेस पर सीधा ऑपरेशन
8 }
9}
10
11// बेहतर विकल्प ✅
12interface DatabaseOperation {
13 execute(): void;
14}
15
16class GoodSingleton {
17 public static getInstance() {
18 // कोड...
19 }
20 public executeOperation(operation: DatabaseOperation) {
21 operation.execute();
22 }
23}
- ग्लोबल म्यूटेबल स्टेट
typescript
1// बचें ❌
2class MutableSingleton {
3 private static instance: MutableSingleton;
4 public globalState: any = {};
5}
6
7// बेहतर विकल्प ✅
8class ImmutableSingleton {
9 private static instance: ImmutableSingleton;
10 private state: Readonly<any>;
11
12 public getState(): Readonly<any> {
13 return this.state;
14 }
15}
पूरक पैटर्न्स 🤝
फैक्टरी + Singleton
typescript
1interface Logger {
2 log(message: string): void;
3}
4
5class LoggerFactory {
6 private static instance: LoggerFactory;
7 private loggers: Map<string, Logger> = new Map();
8
9 private constructor() {}
10
11 public static getInstance(): LoggerFactory {
12 if (!LoggerFactory.instance) {
13 LoggerFactory.instance = new LoggerFactory();
14 }
15 return LoggerFactory.instance;
16 }
17
18 public getLogger(type: 'console' | 'file'): Logger {
19 if (!this.loggers.has(type)) {
20 this.loggers.set(type, this.createLogger(type));
21 }
22 return this.loggers.get(type);
23 }
24
25 private createLogger(type: 'console' | 'file'): Logger {
26 // विशिष्ट logger का निर्माण
27 return type === 'console' ? new ConsoleLogger() : new FileLogger();
28 }
29}
उन्नत चुनौती 🎯
एक ऐसा Singleton बनाएं जो:
- थ्रेड-सेफ हो
- लेजी इनिशियलाइजेशन का उपयोग करे
- टेस्टिंग के लिए रीसेट की अनुमति दे
- वर्जनिंग सिस्टम को एकीकृत करे
अंतिम शब्द 🎬
Singleton एक शक्तिशाली पैटर्न है, लेकिन इसके कार्यान्वयन में सोच-समझ की जरूरत है। सरल मामलों के लिए बेसिक वर्जन पर्याप्त है, लेकिन जटिल एप्लिकेशन के लिए उन्नत वर्जन अधिक मजबूती और लचीलापन प्रदान करते हैं।
प्रो टिप्स 💡
- महंगे संसाधनों के लिए लेजी इनिशियलाइजेशन का उपयोग करें
- हमेशा टेस्टेबिलिटी के बारे में सोचें
- जहां संभव हो डिपेंडेंसी इंजेक्शन को प्राथमिकता दें
- अपने Singleton के उपयोग के मामलों को अच्छी तरह से डॉक्यूमेंट करें
प्रैक्टिकल अभ्यास 🎮
- एप्लिकेशन कॉन्फ़िगरेशन प्रबंधन के लिए एक Singleton बनाएं
- मैसेज क्यू के साथ एक थ्रेड-सेफ Singleton बनाएं
- Singleton पैटर्न का उपयोग करते हुए एक कैशिंग सिस्टम विकसित करें
हैप्पी कोडिंग! 🚀