निर्माता बनाम कारखाने के तरीके [बंद]


181

जब मॉडलिंग कक्षाएं, प्रारंभिक करने का पसंदीदा तरीका क्या है:

  1. कंस्ट्रक्टर, या
  2. फैक्टरी के तरीके

और दोनों में से किसी एक का उपयोग करने के लिए क्या विचार होंगे?

कुछ स्थितियों में, मैं एक फैक्ट्री पद्धति का होना पसंद करता हूं, जो यदि ऑब्जेक्ट का निर्माण नहीं कर सकती है तो वह अशक्त हो जाती है। इससे कोड साफ-सुथरा हो जाता है। मैं बस जांच कर सकता हूं कि क्या लौटाया गया मूल्य वैकल्पिक कार्रवाई करने से पहले अशक्त नहीं है, इसके विपरीत निर्माणकर्ता से एक अपवाद को फेंकने के साथ। (मैं व्यक्तिगत रूप से अपवाद पसंद नहीं करता)

कहते हैं, मेरे पास एक वर्ग पर एक निर्माता है जो एक आईडी मूल्य की अपेक्षा करता है। निर्माणकर्ता इस मान का उपयोग डेटाबेस से कक्षा को पॉप्युलेट करने के लिए करता है। इस मामले में जहां निर्दिष्ट आईडी के साथ एक रिकॉर्ड मौजूद नहीं है, निर्माणकर्ता एक RecordNotFoundException को फेंकता है। इस मामले में मुझे ऐसे सभी वर्गों के निर्माण की कोशिश करनी होगी, जो एक ब्लॉक..चेक ब्लॉक के भीतर हैं।

इसके विपरीत मेरे पास उन वर्गों पर एक स्थिर कारखाना विधि हो सकती है जो रिकॉर्ड नहीं मिलने पर अशक्त हो जाएंगे।

इस मामले में कौन सा दृष्टिकोण बेहतर है, निर्माता या कारखाना विधि?

जवाबों:


66

डिजाइन पैटर्न के पेज 108 से : गामा, हेल्म, जॉनसन और व्लाइसीड्स द्वारा पुन: प्रयोज्य वस्तु-उन्मुख सॉफ्टवेयर के तत्व।

जब फैक्टरी विधि पैटर्न का उपयोग करें

  • एक वर्ग वस्तुओं के वर्ग का अनुमान नहीं लगा सकता है जो इसे बनाना होगा
  • एक वर्ग चाहता है कि उसके उपवर्गों द्वारा बनाई गई वस्तुओं को निर्दिष्ट किया जाए
  • कक्षाएं कई सहायक उपवर्गों में से एक को जिम्मेदारी सौंपती हैं, और आप यह जानना चाहते हैं कि कौन सा सहायक उपवर्ग प्रतिनिधि है

21
स्टेटिक फैक्ट्री विधि गोफ डिज़ाइन पैटर्न से अलग है - फ़ैक्टरी विधि पैटर्न। stackoverflow.com/questions/929021/…
श्री राम

कृपया फैक्ट्री मेथड गो पैटर्न के पैटर्न के साथ तुलना न करें।
श्री राम

137
यह मुझे कुछ नहीं समझाता है
सुशांत

@ सुशांत, ऐसा क्यों है?
पॉलड

2
यह उत्तर उस प्रश्न का उत्तर नहीं देता है, बस अवधारणा को समझने / समझाने के लिए पढ़ने के लिए जानकारी का संबंध है ... यह एक टिप्पणी का अधिक है।
Crt

202

अपने आप से पूछें कि वे क्या हैं और हमारे पास क्यों हैं। वे दोनों एक वस्तु का उदाहरण बनाने के लिए वहाँ हैं।

ElementarySchool school = new ElementarySchool();
ElementarySchool school = SchoolFactory.Construct(); // new ElementarySchool() inside

अब तक कोई अंतर नहीं। अब कल्पना करें कि हमारे पास विभिन्न स्कूल प्रकार हैं और हम एलीमेंटरीस्कूल का उपयोग करके हाईस्कूल में स्विच करना चाहते हैं (जो एलीमेंट्रीस्कूल से लिया गया है या एलीमेंटरीस्कूल के समान इंटरफ़ेस को लागू करता है)। कोड परिवर्तन होगा:

HighSchool school = new HighSchool();
HighSchool school = SchoolFactory.Construct(); // new HighSchool() inside

एक इंटरफ़ेस के मामले में हमारे पास होगा:

ISchool school = new HighSchool();
ISchool school = SchoolFactory.Construct(); // new HighSchool() inside

अब यदि आपके पास कई स्थानों पर यह कोड है तो आप देख सकते हैं कि फ़ैक्टरी विधि का उपयोग करना बहुत सस्ता हो सकता है क्योंकि एक बार जब आप फ़ैक्टरी विधि को बदल देते हैं (यदि हम इंटरफेस के साथ दूसरे उदाहरण का उपयोग करते हैं)।

और यह मुख्य अंतर और लाभ है। जब आप एक जटिल श्रेणी पदानुक्रम के साथ काम करना शुरू करते हैं और आप इस तरह के पदानुक्रम से गतिशील रूप से एक वर्ग का एक उदाहरण बनाना चाहते हैं तो आपको निम्न कोड मिलता है। फैक्ट्री के तरीके फिर एक पैरामीटर ले सकते हैं जो उस विधि को बताता है जो तात्कालिकता के लिए क्या ठोस उदाहरण है। मान लीजिए कि आपके पास एक MyStudent क्लास है और आपको उसी इस्कूल ऑब्जेक्ट को इंस्टेंट करना होगा, ताकि आपका छात्र उस स्कूल का सदस्य हो।

ISchool school = SchoolFactory.ConstructForStudent(myStudent);

अब आपके पास अपने ऐप में एक जगह है जिसमें व्यावसायिक तर्क शामिल हैं जो यह निर्धारित करता है कि विभिन्न IStudent ऑब्जेक्ट्स के लिए IS IS का उद्देश्य क्या है।

इसलिए - साधारण कक्षाओं (मूल्य वस्तुओं, आदि) के लिए कंस्ट्रक्टर ठीक है (आप अपने आवेदन को अधिक करना नहीं चाहते हैं) लेकिन जटिल वर्ग पदानुक्रम के लिए कारखाना विधि एक पसंदीदा तरीका है।

इस तरह आप चार पुस्तक "एक इंटरफेस के कार्यक्रम, एक कार्यान्वयन नहीं" के गिरोह से पहले डिजाइन सिद्धांत का पालन करते हैं ।


2
यहां तक ​​कि जब आपको लगता है कि यह एक साधारण वर्ग है, तो एक मौका है कि किसी को आपके साधारण वर्ग का विस्तार करने की आवश्यकता है, इसलिए कारखाना विधि अभी भी बेहतर है। उदाहरण के लिए आप एलीमेंट्रीस्कूल से शुरू कर सकते हैं लेकिन बाद में कोई व्यक्ति (स्वयं को शामिल करके) इसे PrivateElementarySchool और PublicElementarySchool के साथ बढ़ा सकता है।
जैक

10
यह स्वीकृत उत्तर होना चाहिए
am05mhz

2
@ डेविड, अच्छा जवाब है, लेकिन क्या आप एक उदाहरण पर विस्तार कर सकते हैं जहां प्रत्येक इंटरफ़ेस कार्यान्वयन में निर्माण के लिए विभिन्न मापदंडों की आवश्यकता हो सकती है। यहाँ एक मूर्खतापूर्ण उदाहरण है: IFood sandwich = new Sandwich(Cheese chz, Meat meat);और IFood soup = new Soup(Broth broth, Vegetable veg);फैक्ट्री और या बिल्डर यहाँ कैसे मदद कर सकते हैं?
ब्रायन

1
मैं सिर्फ कारखाने के उपयोग के उद्देश्य पर तीन अन्य स्पष्टीकरण पढ़ता हूं, और यह वह है जो अंत में मेरे लिए "क्लिक" था। धन्यवाद!
डैनियल पीरानो

इसका उत्तर क्यों नहीं दिया गया?
टॉमस

74

आपको पढ़ने की आवश्यकता है (यदि आपके पास पहुंच है) प्रभावी जावा 2 आइटम 1: कंस्ट्रक्टरों के बजाय स्थैतिक कारखाने के तरीकों पर विचार करें

स्थैतिक कारखाने तरीकों लाभ:

  1. उनके नाम हैं।
  2. उन्हें हर बार एक नई वस्तु बनाने की आवश्यकता नहीं होती है।
  3. वे अपने रिटर्न प्रकार के किसी भी उपप्रकार की वस्तु को वापस कर सकते हैं।
  4. वे मानकीकृत प्रकार के उदाहरण बनाने की क्रियाशीलता को कम करते हैं।

स्थैतिक कारखाने तरीकों नुकसान:

  1. केवल स्थैतिक कारखाने के तरीके प्रदान करते समय, सार्वजनिक या संरक्षित निर्माणकर्ताओं के बिना वर्गों को उपवर्गित नहीं किया जा सकता है।
  2. वे अन्य स्थिर तरीकों से आसानी से अलग नहीं हैं

4
यह मुझे लगता है कि जावा में एक गंभीर बग है, तो एक सामान्य OOD समस्या है। ऐसी कई OO भाषाएँ हैं जिनके पास निर्माणकर्ता भी नहीं हैं , फिर भी सबक्लासिंग ठीक काम करता है।
जोर्ग डब्ल्यू मित्तग

1
@cherouvim ज्यादातर कंसट्रक्टर्स का उपयोग करते हुए क्यों लिखा जाता है अगर( factory methods are better than Constructors. ( Item-1 ) ) Effective java
आसिफ मुश्ताक

अच्छे अंक। हालांकि यह जावा विशिष्ट है। एक भाषा सुविधा के लिए एक मामला बनाया जा सकता है जो कारखाने के तरीकों को अन्य स्थिर तरीकों से अलग बनाता है।
OCDev

30

डिफ़ॉल्ट रूप से, बिल्डरों को प्राथमिकता दी जानी चाहिए, क्योंकि वे समझने और लिखने में सरल हैं। हालाँकि, यदि आपको विशेष रूप से किसी वस्तु के निर्माण की बारीकियों को उसके अर्थ अर्थ से अलग करने की आवश्यकता है जैसा कि क्लाइंट कोड द्वारा समझा गया है, तो आप कारखानों का उपयोग करना बेहतर होगा।

कंस्ट्रक्टर्स और कारखानों के बीच का अंतर, एक वेरिएबल के लिए, एक वेरिएबल और एक पॉइंटर के अनुरूप है। अप्रत्यक्ष स्तर का एक और स्तर है, जो एक नुकसान है; लेकिन लचीलेपन का एक और स्तर भी है, जो एक फायदा है। इसलिए चुनाव करते समय, आपको यह लागत बनाम लाभ विश्लेषण करने की सलाह दी जाएगी।


17
तो, (टीडीडी शैली) आप निर्माणकर्ताओं के साथ काम शुरू करने के सबसे सरल तरीके के रूप में शुरू करेंगे। और फिर कारखानों में रिफैक्टर एक बार आपको कोड स्मेल मिलना शुरू हो जाता है (जैसे बार-बार सशर्त लॉजिक यह निर्धारित करना कि किस कंस्ट्रक्टर को कॉल करना है)?
एंडीएम

1
बहुत महत्वपूर्ण बिंदु। कारखानों और कंस्ट्रक्टर्स की तुलना करते हुए एक उपयोगकर्ता अध्ययन में अत्यधिक महत्वपूर्ण परिणाम मिले, जो दर्शाता है कि फैक्ट्रियां एपीआई प्रयोज्य के लिए हानिकारक हैं: "उपयोगकर्ताओं को एक निर्माता के साथ एक कारखाने के साथ एक वस्तु का निर्माण करने के लिए काफी अधिक समय (p = 0.005) की आवश्यकता होती है" [एपीआई पैटर्न में फैक्टरी पैटर्न : एक उपयोगिता मूल्यांकन ]।
mdeff

12

एक कारखाने का उपयोग केवल तब करें जब आपको ऑब्जेक्ट निर्माण के साथ अतिरिक्त नियंत्रण की आवश्यकता होती है, इस तरह से जो निर्माणकर्ताओं के साथ नहीं किया जा सकता है।

कारखानों में उदाहरण के लिए कैशिंग की संभावना है।

कारखानों का उपयोग करने का दूसरा तरीका एक परिदृश्य में है जहां आप उस प्रकार को नहीं जानते हैं जिसे आप निर्माण करना चाहते हैं। अक्सर आप इस प्रकार का उपयोग प्लगइन फैक्टरी परिदृश्यों में देखते हैं, जहां प्रत्येक प्लगइन को बेसकलैस से प्राप्त करना चाहिए या किसी प्रकार का इंटरफ़ेस लागू करना चाहिए। कारखाना उन वर्गों के उदाहरण बनाता है जो बेसकेल्स से निकलते हैं या जो इंटरफ़ेस को लागू करते हैं।


11

"प्रभावी जावा", द्वितीय संस्करण, आइटम 1 से एक हवाला देते हैं: निर्माणकर्ताओं के बजाय स्थैतिक कारखाने के तरीकों पर विचार करें, पी। 5:

"ध्यान दें कि एक स्टैटिक फ़ैक्टरी विधि डिज़ाइन पैटर्न [Gamma95, पृष्ठ 107] से फैक्ट्री मेथड पैटर्न के समान नहीं है । इस मद में वर्णित स्टैटिक फ़ैक्टरी विधि का डिज़ाइन पैटर्न में कोई सीधा समकक्ष नहीं है।"


10

के अलावा "प्रभावी जावा" (एक और जवाब में उल्लेख किया), एक और क्लासिक किताब भी पता चलता है:

ओवरलोड निर्माणकर्ताओं के लिए स्थैतिक कारखाने के तरीकों (उन नामों के साथ जो तर्कों का वर्णन करते हैं) को प्राथमिकता दें।

उदाहरण के लिए। मत लिखो

Complex complex = new Complex(23.0);

बल्कि लिखें

Complex complex = Complex.fromRealNumber(23.0);

Complex(float)उपयोगकर्ता को फैक्ट्री को निजी बनाने का सुझाव देने के लिए यह पुस्तक उतनी ही दूर तक जाती है, जितनी कि उपयोगकर्ता को स्टैटिक फैक्ट्री पद्धति को कॉल करने के लिए मजबूर करना।


2
किताब के उस हिस्से को पढ़कर मुझे यहाँ लाया
पर्पल

1
@Bayrem: मुझे भी, मैं इसे हाल ही में पढ़ रहा था और सोचा कि मुझे इसे उत्तरों में जोड़ना चाहिए।
ब्लू_नोट

1
एक संबंधित नोट पर, आप सहायक हो सकते हैं कुछ नामकरण रिवाजों का द्वारा बाहर काम किया java.time ढांचे के नामकरण के बारे में from…, to…, parse…, with…, और इतने पर। ध्यान रखें कि java.time कक्षाएं अपरिवर्तनीय बनाने के लिए बनाई गई हैं, लेकिन इनमें से कुछ नामकरण परंपराएँ उत्परिवर्तित कक्षाओं के साथ भी उपयोगी हो सकती हैं।
बेसिल बोर्के

7

सीएडी / सीएएम एप्लिकेशन से एक ठोस उदाहरण।

एक कंस्ट्रक्टर का उपयोग करके एक कटिंग पथ बनाया जाएगा। यह लाइनों की एक श्रृंखला है और आर्क्स कट करने के लिए एक मार्ग को परिभाषित करता है। जबकि लाइनों और चापों की श्रृंखला अलग-अलग हो सकती है और अलग-अलग निर्देशांक होते हैं जो आसानी से एक निर्माणकर्ता में एक सूची पारित करके नियंत्रित करते हैं।

एक कारखाने का उपयोग करके एक आकृति बनाई जाएगी। क्योंकि जहां एक आकार वर्ग होता है, प्रत्येक आकार अलग-अलग तरीके से सेटअप होता है, यह इस बात पर निर्भर करता है कि वह किस प्रकार का है। हमें नहीं पता कि हम किस आकार को शुरू करने जा रहे हैं जब तक उपयोगकर्ता चयन नहीं करता है।


5

कहते हैं, मेरे पास एक वर्ग पर एक निर्माता है जो एक आईडी मूल्य की अपेक्षा करता है। निर्माणकर्ता इस मान का उपयोग डेटाबेस से कक्षा को पॉप्युलेट करने के लिए करता है।

यह प्रक्रिया निश्चित रूप से एक निर्माणकर्ता के बाहर होनी चाहिए।

  1. कंस्ट्रक्टर को डेटाबेस तक नहीं पहुंचना चाहिए।

  2. एक निर्माणकर्ता का कार्य और कारण डेटा सदस्यों को आरम्भ करना और निर्माणकर्ता में पारित मूल्यों का उपयोग करके वर्ग अपरिवर्तनीयता स्थापित करना है

  3. बाकी सब चीजों के लिए एक बेहतर तरीका यह है कि स्टैटिक फैक्ट्री विधि या अधिक जटिल मामलों में एक अलग फैक्ट्री या बिल्डर क्लास का उपयोग किया जाए।

Microsoft से कुछ निर्माता गाइड लाइन :

कंस्ट्रक्टर में कम से कम काम करें। कंस्ट्रक्टर्स मापदंडों को कैप्चर करने के अलावा कंस्ट्रक्टर्स को ज्यादा काम नहीं करना चाहिए। आवश्यकता होने तक किसी अन्य प्रसंस्करण की लागत में देरी होनी चाहिए।

तथा

एक निर्माणकर्ता के बजाय एक स्थिर कारखाने विधि का उपयोग करने पर विचार करें यदि वांछित ऑपरेशन के शब्दार्थ सीधे एक नए उदाहरण के निर्माण के लिए मैप नहीं करते हैं।


2

कभी-कभी आपको ऑब्जेक्ट बनाते समय कुछ मूल्यों / शर्तों की जांच / गणना करनी होती है। और अगर यह एक अपवाद फेंक सकता है - तो निर्माण बहुत बुरा तरीका है। तो आपको ऐसा कुछ करने की आवश्यकता है:

var value = new Instance(1, 2).init()
public function init() {
    try {
        doSome()
    }
    catch (e) {
        soAnotherSome()
    }
}

जहां सभी अतिरिक्त गणना init () में हैं। लेकिन केवल आप डेवलपर के रूप में इस init () के बारे में जानते हैं। और हां, महीनों के बाद आप इसके बारे में भूल जाते हैं। लेकिन अगर आपके पास एक कारखाना है - तो बस इस इनिट () को सीधे कॉल से छिपाने के साथ आपको एक विधि की आवश्यकता है - इसलिए कोई समस्या नहीं है। इस दृष्टिकोण के साथ निर्माण और स्मृति लीक पर गिरने के साथ कोई समस्या नहीं है।

किसी ने आपको कैशिंग के बारे में बताया। यह अच्छा है। लेकिन आपको फ्लाईवेट पैटर्न के बारे में भी याद रखना होगा जो कि फैक्ट्री के तरीके के साथ उपयोग करना अच्छा है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.