परिचय
सार्वजनिक कंस्ट्रक्टर कक्षाओं के उदाहरण बनाने का पारंपरिक तरीका है।
```javascript public class Member {
}
public enum MemberStatus {
}
सामान्य तौर पर, पब्लिक कंस्ट्रक्टर पर्याप्त होते हैं, लेकिन निर्माताओं के अलावा, स्थिर कारखाने के तरीके (स्टैटिक फैक्ट्री मेथड) प्रदान करने से उपयोगकर्ताओं के लिए वांछित उदाहरण बनाना आसान हो सकता है।
स्थिर कारखाने विधियों का एक प्रमुख उदाहरण बूलियन का valueof () विधि है।
```javascript public static Boolean valueOf(boolean b) { return b ? Boolean.TRUE : Boolean.FALSE; }
उपरोक्त विधि एक बूलियन मान लेती है जो एक मूल प्रकार है और उसे वापस करने के लिए एक बूलियन ऑब्जेक्ट बनाती है।
स्थिर कारखाने विधियों के लाभ
नाम रखा जा सकता है।
ऐसे नाम का उपयोग कंस्ट्रक्टर बनाने में मदद करता है। यदि किसी कंस्ट्रक्टर का नाम लंबा है और उसे याद रखना मुश्किल है, तो आप एक ही हस्ताक्षर के साथ एक स्थिर फैक्ट्री विधि बना सकते हैं और इसे उपयोगकर्ता के लिए समझने में आसान नाम दे सकते हैं।
उदाहरण के लिए, मान लें कि आपके पास एक कंस्ट्रक्टर है जो पहले नाम, अंतिम नाम, आयु, व्यवसाय और वेतन लेता है। इस कंस्ट्रक्टर के लिए एक अच्छा नाम खोजना मुश्किल हो सकता है जो सभी मापदंडों को स्पष्ट रूप से इंगित करता है। हालांकि, आप इसके बजाय एक स्टैटिक फैक्ट्री विधि बना सकते हैं जिसका नाम 'क्रिएटएम्प्लॉयी' है और वही पैरामीटर लें। इससे उपयोगकर्ताओं के लिए फ़ंक्शन के उद्देश्य को आसानी से समझना आसान हो जाएगा।
उदाहरण के लिए, Member वर्ग के उपर्युक्त मुख्य कंस्ट्रक्टर (नाम, आयु, शौक, सदस्य स्थिति) को देखते हुए, किसी को यह पहचानना मुश्किल होगा कि यह किस प्रकार का सदस्य है।
इसके अतिरिक्त, एक हस्ताक्षर के साथ केवल एक ही कंस्ट्रक्टर बनाया जा सकता है, जबकि एक स्थिर फैक्ट्री विधि का नाम हो सकता है, इसलिए एक ही हस्ताक्षर के साथ उदाहरण वापस करने के लिए कई स्थिर फैक्ट्री विधियों को बनाया जा सकता है।
```javascript public class Member {
}
जैसा कि ऊपर दिखाया गया है, कंस्ट्रक्टर में सदस्य की स्थिति को अलग करने की तुलना में, एक ही हस्ताक्षर के साथ कई स्थिर फैक्ट्री विधियों को बनाकर, उपयोगकर्ता किसी विशेष कौशल वाले सदस्य उदाहरण बना सकते हैं, बिना किसी भ्रम के।
जेडीके द्वारा परिभाषित लाइब्रेरी को देखते हुए, बिगइंटेगर का स्थिर फैक्ट्री विधि, प्रोबेबलप्राइम() मौजूद है।
```javascript public static BigInteger probablePrime(int bitLength, Random rnd) { if (bitLength < 2) throw new ArithmeticException("bitLength < 2");
}
बिगइंटेगर के सामान्य कंस्ट्रक्टर और बिगइंटेगर प्रोबेबलप्राइम() की स्थिर फैक्ट्री विधि की तुलना करते समय, 后 वाला उस स्थिति का बेहतर वर्णन करेगा जहां बिगइंटेगर मान लौटाया गया है
हर बार कॉल किए जाने पर इंस्टेंस को री-क्रिएट करने की आवश्यकता नहीं है।
```javascript public static Boolean valueOf(boolean b) { return (b ? Boolean.TRUE : Boolean.FALSE); }
बूलियन का वेल्यूऑफ़() विधि को देखने से हम पाते हैं कि एक कैशिंग मैकेनिज्म शामिल है जहां कैश्ड किए गए मूल्य को वापस कर दिया जाता है। इस विशेषता से प्रदर्शन में उल्लेखनीय सुधार हो सकता है यदि अनुरोध की जाने वाली वस्तु महंगी है,फ्लाईवेट पैटर्नइसी तरह की तकनीक को भी माना जा सकता है।
एक क्लास जो स्थिर फैक्ट्री विधि विधि का उपयोग करता है जो समान वस्तु को दोहराए गए अनुरोधों पर वापस करता है, उसे इंस्टेंस नियंत्रण वर्ग कहा जाता है। इंस्टेंस को नियंत्रित करके, आप सिंगलटन क्लास बना सकते हैं या गैर-इंस्टेंटिएटेबल क्लास बना सकते हैं। आप यह भी सुनिश्चित कर सकते हैं कि अपरिवर्तनीय मूल्य वर्ग में केवल एक ही इंस्टेंस मौजूद है।
इंस्टेंस नियंत्रण फ्लाईवेट पैटर्न का आधार है और एनम यह गारंटी देता है कि केवल एक ही इंस्टेंस बनाया गया है।
उदाहरण
हमें माइनक्राफ्ट में एक पेड़ लगाना है। अगर हम प्रति पेड़ ऑब्जेक्ट बनाते हैं, तो हमारे पास मेमोरी ओवरफ्लो की संभावना है।
इसलिए, लाल और हरे रंग के पेड़ों की तरह, इन वस्तुओं को सहेजा जाता है, केवल स्थान को बदल दिया जाता है और वापस कर दिया जाता है। बेशक, रंग 2 से अधिक रंगों में बढ़ सकते हैं, इसलिएवृक्षों को संग्रहीत करने के लिए रंग के अनुसार एक नक्शा जैसी डेटा संरचना कुशल होगी।
```javascript public class Tree {
}
public class TreeFactory { // HashMap डेटा संरचना का उपयोग करके बनाए गए पेड़ों को प्रबंधित करें। public static final Map<String, Tree> treeMap = new HashMap<>();
}
public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in);
}
सिंगलटन पैटर्न के साथ अंतर
सिंगलटन पैटर्न यह सुनिश्चित करता है कि पेड़ वर्ग में केवल एक ही पेड़ बनाया जा सकता है। इसलिए, यदि आप सिंगलटन पैटर्न का उपयोग करते हैं, तो आपको रंग की परवाह किए बिना बनाए गए एकल वस्तु का रंग बदलना होगा।अर्थात, सिंगलटन पैटर्न बिना किसी भिन्नता के केवल एक ही वस्तु रख सकता है।
उपयोग के मामले
जावा के स्ट्रिंग कॉस्टेंट पूल में फ्लाईवेट पैटर्न का उपयोग किया जाता है।
आप उपवर्ग वस्तुओं को विभिन्न वापसी प्रकारों के साथ वापस कर सकते हैं।
यदि आपने कभी एरेज यूटिलिटीज क्लास की एजलिस्ट () विधि का उपयोग किया है, तो आप इस लाभ को समझेंगे।
```javascript
public static
वापसी मानों को ArrayList जैसे ArrayList के उप प्रकार में लपेटा जाता है, लेकिन उपयोगकर्ताओं को इस कार्यान्वयन को जानने की आवश्यकता नहीं है। अर्थात, क्योंकि वापसी वस्तु के वर्ग का चयन स्वतंत्र रूप से किया जा सकता है, यह लचीलापन होता है जो डेवलपर्स को कार्यान्वयन को उजागर किए बिना कार्यान्वयन वापस करने की अनुमति देता है ताकि एपीआई को छोटा रखा जा सके
जावा इंटरफ़ेस के बारे में स्थिर विधि
जावा 8 से पहले, इंटरफेस में स्थिर विधियों को घोषित करना असंभव था, और "प्रकार" नाम की एक इंटरफेस से जुड़ी एक स्थिर विधि लौटाने के लिए, इसे विधियों को परिभाषित करने वाले" टाइप्स" नामक एक गैर-इंस्टेंटिएटेबल साथी वर्ग बनाया गया था।
जावा संग्रह रूपरेखा (JCF) में 45 प्रदाता कार्यान्वयन हैं और इनमें से अधिकांश कार्यान्वयन एक ही सहयोगी वर्ग java.util.Collections में केवल एक स्थिर फैक्ट्री विधि के माध्यम से उपलब्ध हैं। विशेष रूप से, इन कार्यान्वयनों में से, जनता नहीं हैं और इसलिए उन्हें केवल स्थिर फैक्ट्री विधि के माध्यम से ही बनाया जा सकता है। (इसके कार्यान्वयन को स्वाभाविक रूप से विरासत में नहीं लिया जा सकता है।)
इसके अतिरिक्त, 45 कार्यान्वयनों को उजागर नहीं किया गया है, इसलिए एपीआई को बहुत छोटा रखा गया है।
```javascript
// इंटरफ़ेस और साथी वर्ग का उदाहरण
List
हालाँकि, जावा 8 से, एक साथी वर्ग को अलग से परिभाषित किए बिना सीधे इंटरफ़ेस में स्थिर विधियाँ जोड़ी जा सकती हैं।
यह विभिन्न निम्न श्रेणी की वस्तुओं को इनपुट पैरामीटर के आधार पर वापस कर सकता है।
केवल निम्न श्रेणियों को वापस करने के अलावा, यह पैरामीटर मान के आधार पर विभिन्न सबटाइप वापस कर सकता है। उदाहरण के लिए, यदि आप अंक के आधार पर सदस्य की स्थिति बदलना चाहते हैं, तो आप निम्न के रूप में एक स्थिर फैक्ट्री विधि बना सकते हैं और उसमें तुलना तर्क सेट कर सकते हैं।
```javascript public enum MemberStatus {
}
@DisplayName("सदस्य स्थिति परीक्षण") class MemberStatusTest {
}
स्थिर फैक्ट्री विधि बनाने के समय उस वस्तु का वर्ग मौजूद नहीं हो सकता है जिससे वापसी होगी।
उपर्युक्त वाक्य में class, वस्तु के वर्ग, यह हमारे द्वारा बनाई गई क्लास फ़ाइल है।
संदर्भ के लिए, Class<?> क्लास लोडर द्वारा क्लास को लोड करते समय हीप क्षेत्र में असाइन की जाने वाली क्लास ऑब्जेक्ट को संदर्भित करता है। इस क्लास ऑब्जेक्ट में हमारे द्वारा बनाई गई क्लास का विभिन्न मेटाडेटा होता है।
```javascript package algorithm.dataStructure;
public abstract class StaticFactoryMethodType {
}
यदि आप ऊपर दिए गए कोड को देखते हैं, तो आप पाएंगे कि इंटरफ़ेस कार्यान्वयन का स्थान परावर्तन का उपयोग करके वास्तविक कार्यान्वयन को आरंभ करने के लिए एक वर्ग ऑब्जेक्ट बनाने के लिए उपयोग किया जाता है। इस समय स्थिर फैक्ट्री विधि लिखते समयStaticFactoryMethodTypeChild वर्ग मौजूद नहीं होना चाहिए।
हालांकि, अगर स्थैतिक फैक्ट्री विधि का उपयोग करते समय algorithm.dataStructure.StaticFactoryMethodTypeChild पथ पर कोई कार्यान्वयन नहीं है, तो एक त्रुटि होती है, लेकिन कोई समस्या नहीं है स्थिर फैक्ट्री विधि को लिखते समय क्योंकि यह लचीला है।
```javascript public interface Test {
}
public class Main {
}
आप प्रतिबिंब का उपयोग किए बिना भी उसी लचीलापन प्राप्त कर सकते हैं। Test का स्थिर फैक्ट्री विधि create() देखते ही, भले ही कोई कार्यान्वयन न हो, लिखने में कोई समस्या नहीं है। बेशक, जब वास्तव में उपयोग किया जाता है, तो एक NPE उत्पन्न होता है, इसलिए आपको बाद में एक कार्यान्वयन वापस करने की आवश्यकता होती है।
यह लचीलापन वह आधार है जिस पर सेवा प्रदाता रूपरेखा बनाई जाती है, जिसका प्रतिनिधि JDBC है। JDBC सेवा प्रदाता रूपरेखा के प्रदाता कार्यान्वयन हैं और रूपरेखा क्लाइंट को कार्यान्वयन प्रदान करने में एक भूमिका निभाती है, जिससे क्लाइंट को कार्यान्वयन से अलग किया जाता है। (डीआईपी)
- सेवा प्रदाता रूपरेखा के घटक
- सेवा इंटरफ़ेस
- कार्यान्वयन व्यवहार को परिभाषित करता है
- JDBC का कनेक्शन
- प्रदाता पंजीकरण एपीआई
- प्रदाता एक कार्यान्वयन पंजीकृत करता है
- JDBC का DriverManager.registerDriver()
- सेवा पहुंच एपीआई
- क्लाइंट सेवा का एक उदाहरण प्राप्त करते समय उपयोग किया जाता है, और जब कोई स्थिति निर्दिष्ट नहीं होती है, तो यह डिफ़ॉल्ट कार्यान्वयन या समर्थित कार्यान्वयन देता है।
- स्थिर फैक्ट्री विधि का समकक्ष
- JDBC का DriverManager.getConnection()
- (विकल्प) सेवा प्रदाता इंटरफ़ेस
- यदि यह मौजूद नहीं है, तो आपको प्रत्येक कार्यान्वयन को प्रतिबिंब का उपयोग करके एक इंस्टेंस के रूप में बनाने की आवश्यकता है
- JDBC का चालक
- सेवा इंटरफ़ेस
सेवा प्रदाता रूपरेखा पैटर्न के कई रूप हैं और पुल पैटर्न और निर्भरता इंजेक्शन रूपरेखा की तरह दिखते हैं।
एक विशिष्ट JDBC उदाहरण
```javascript Class.forName("oracle.jdbc.driver.OracleDriver"); Connection connection = null; connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:ORA92", "root", "root");
// विभिन्न कथनों का उपयोग कर sql तर्क
सामान्य तौर पर, JDBC को ऊपर की तरह लिखा जाता है। Class.forName() का उपयोग करके, OracleDriver जैसे ड्राइवर कार्यान्वयन में से एक पंजीकृत है, और DriverManager.getConnection() का उपयोग करके, कनेक्शन OracleDriver जैसे कनेक्शन कार्यान्वयन में से एक है।
यहां, हम देख सकते हैं कि Connection सेवा इंटरफ़ेस है, DriverManager.getConnection() सेवा एक्सेस एपीआई है, और Driver सेवा प्रदाता इंटरफ़ेस है। हालाँकि, DriverManager.registerDriver() जिसे प्रदाता पंजीकरण API कहा जाता है, का उपयोग नहीं किया गया था। फिर भी, हम Class.forName() का उपयोग करके OracleDriver जैसे ड्राइवर कार्यान्वयन को पंजीकृत कर सकते हैं। यह कैसे संभव है?
Class.forName() का संचालन सिद्धांत
यह विधि एक भौतिक वर्ग फ़ाइल नाम इनपुट के रूप में लेती है और JVM से क्लास लोड करने का अनुरोध करती है। फिर क्लास लोडर क्लास के मेटाडेटा को विधि क्षेत्र में संग्रहीत करता है, जबकिस्टेटिक फ़ील्ड और स्टेटिक ब्लॉक को इनिशियलाइज़ किया गया है। इस समय, प्रदाता पंजीकरण एपीआई का उपयोग किया जाता है।
```javascript public class OracleDriver implements Driver {
}
वास्तव में, OracleDriver को देखते हुए, हम देख सकते हैं किDriverManager.registerDriver() का उपयोग करके स्टैटिक ब्लॉक मेंOracleDriver जैसे ड्राइवर कार्यान्वयन पंजीकृत है।
DriverManager वर्ग विश्लेषण
```javascript public class DriverManager {
}
हालांकि DriverManager वास्तव में बहुत अधिक जटिल है, यह एक सरलीकृत संस्करण है यदि आपके पास गहन नहीं है। उपरोक्त explanation के अनुसार, यह registerDriver() को OracleDriver के स्टैटिक ब्लॉक में कहता है और OracleDriver को पंजीकृत करता है, और उपयोगकर्ताgetConnection() को कॉल करके कनेक्शन कार्यान्वयन प्राप्त कर सकता है।
यदि आप ड्राइवर इंटरफ़ेस से Connection प्राप्त कर रहे हैं, तो अधिक विस्तार से देखें, आप पाएंगे कि कनेक्शन कार्यान्वयन ड्राइवर इंटरफ़ेस से प्राप्त होता है। यदि कोई सेवा प्रदाता इंटरफ़ेस, ड्राइवर जैसा मौजूद नहीं है, तो आपको Class.forName() जैसे रिफ्लेक्शन का उपयोग करके कनेक्शन कार्यान्वयन वापस करने की आवश्यकता हो सकती है जिसे आप चाहते हैं। इस समय, आपके द्वारा उस समय Connection कार्यान्वयन नहीं बनाया जाएगा जिसके बारे में आपने स्थिर फैक्ट्री लिखी थी।
इसके बजाय, हम ड्राइवर इंटरफ़ेस का उपयोग करके गतिशील रूप से ड्राइवर कार्यान्वयन पंजीकृत करते हैं और ड्राइवर के अनुसार Connection कार्यान्वयन आसानी से प्राप्त कर सकते हैं।
संदर्भ के लिए, मैं DriverManager के getConnection() विधि का वास्तविक JDK कोड देखता हूं, लेकिन आप इसे छोड़ सकते हैं जब तक कि आपके पास इसमें कोई विशेष रुचि न हो।
```javascript @CallerSensitive public static Connection getConnection(String url, String user, String password) throws SQLException { java.util.Properties info = new java.util.Properties();
}
सर्वप्रथम, सार्वजनिक static विधि getConnection() को कॉल किया जाता है, और url, Properties और CallerClass निजी स्थिर विधि getConnection() के इनपुट के रूप में पारित किए जाते हैं। इस समय, Reflection.getCallerClass() वह वर्ग प्राप्त करने की भूमिका निभाता है जिसने public static विधि getConnection() को कॉल किया है। यदि Car वर्ग ने getConnection() को कॉल किया है, तो आप CallerClass द्वारा वर्ग ऑब्जेक्ट प्राप्त कर सकते हैं।
```javascript private static Connection getConnection(String url, java.util.Properties info, Class<?> caller) throws SQLException { ClassLoader callerCL = caller != null ? caller.getClassLoader() : null; synchronized(DriverManager.class) { if (callerCL == null) { callerCL = Thread.currentThread().getContextClassLoader(); } }
}
callerCL एक क्लास लोडर ऑब्जेक्ट है और इसे caller's क्लास लोडर या वर्तमान थ्रेड के क्लास लोडर द्वारा बनाया जाता है। उसके बाद, वह वर्तमान एप्लिकेशन में पंजीकृत ड्राइवर सूची, registeredDrivers, एक-एक करके aDriver प्राप्त करता है। और यदि यह aDriver isDriverAllowed() द्वारा true के रूप में आता है, तो इस ड्राइवर द्वारा Connection ऑब्जेक्ट प्राप्त करें और इसे वापस करें। isDriverAllowed() caller की aDriver की अनुमति की जांच करने का काम करता है।
JDBC फ्रेमवर्क के लाभ
JDBC फ्रेमवर्क का मुख्य बिंदु यह है कि ड्राइवर, कनेक्शन इंटरफ़ेस और उनके संबंधित वास्तविक कार्यान्वयन वर्ग पूरी तरह से अलग और प्रदान किए जाते हैं। इंटरफ़ेस का उपयोग करके फ्रेमवर्क बनाएं और प्रत्येक फ्रेमवर्क के अनुसार कार्यान्वयन वर्ग बनाएं। यह बहुत लचीला है क्योंकि यह बहुत लचीला है।
इसलिए, भले ही एक और डीबीएमएस सामने आए, विक्रेता ड्राइवर और कनेक्शन इंटरफ़ेस को लागू करके और प्रदान करके जावा का उपयोग कर रहे डेवलपर्स को उसी एपीआई का उपयोग करने देगा।
टिप्पणियाँ0