मुझे प्रत्यक्ष वस्तु निर्माण के बजाय कारखाने वर्ग का उपयोग क्यों करना चाहिए?


162

मैंने GitHub और CodePlex पर कई С # और Java क्लास की लाइब्रेरी परियोजनाओं का इतिहास देखा है, और मैं प्रत्यक्ष वस्तु तात्कालिकता के विपरीत कारखाने की कक्षाओं में स्विच करने की प्रवृत्ति देखता हूं।

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

ऐसा परिवर्तन क्यों उपयोगी होगा? इस तरह से रिफैक्ट करने का क्या मतलब है? स्थैतिक कारखाने विधि कॉल के साथ सार्वजनिक वर्ग के रचनाकारों को कॉल को बदलने के क्या लाभ हैं?

मुझे सार्वजनिक निर्माणकर्ताओं का उपयोग कब करना चाहिए, और मुझे कारखानों का उपयोग कब करना चाहिए?



1
एक कपड़े वर्ग / विधि क्या है?
डोभाल

जवाबों:


56

फैक्ट्री कक्षाएं अक्सर कार्यान्वित की जाती हैं क्योंकि वे परियोजना को ठोस सिद्धांतों का अधिक बारीकी से पालन करने की अनुमति देते हैं । विशेष रूप से, इंटरफ़ेस अलगाव और निर्भरता उलटा सिद्धांत।

कारखानों और इंटरफेस बहुत अधिक दीर्घकालिक लचीलेपन की अनुमति देते हैं। यह एक और अधिक decoupled के लिए अनुमति देता है - और इसलिए अधिक परीक्षण योग्य - डिजाइन। यहाँ एक गैर-विस्तृत सूची है कि आप इस रास्ते पर क्यों जा सकते हैं:

  • यह आपको नियंत्रण (IoC) कंटेनर के व्युत्क्रम को आसानी से पेश करने की अनुमति देता है
  • यह आपके कोड को अधिक परीक्षण योग्य बनाता है क्योंकि आप इंटरफेस को मॉक कर सकते हैं
  • यह आपको एप्लिकेशन को बदलने का समय आने पर बहुत अधिक लचीलापन देता है (यानी आप निर्भर कोड को बदले बिना नए कार्यान्वयन बना सकते हैं)

इस स्थिति पर विचार करें।

असेंबली A (-> का अर्थ इस पर निर्भर करता है):

Class A -> Class B
Class A -> Class C
Class B -> Class D

मैं क्लास बी को असेंबली बी में ले जाना चाहता हूं, जो असेंबली ए पर निर्भर है। इन ठोस निर्भरताओं के साथ मुझे अपनी पूरी क्लास पदानुक्रम को पार करना होगा। यदि मैं इंटरफेस का उपयोग करता हूं, तो मैं बहुत दर्द से बच सकता हूं।

विधानसभा ए:

Class A -> Interface IB
Class A -> Interface IC
Class B -> Interface IB
Class C -> Interface IC
Class B -> Interface ID
Class D -> Interface ID

मैं अब कक्षा B को असेंबली B में ले जा सकता हूं, जिसमें कोई दर्द नहीं है। यह अभी भी विधानसभा ए में इंटरफेस पर निर्भर करता है।

अपनी निर्भरता को हल करने के लिए एक IoC कंटेनर का उपयोग करना आपको और भी अधिक लचीलापन देता है। जब भी आप क्लास की निर्भरता को बदलते हैं, तो कंस्ट्रक्टर को प्रत्येक कॉल को अपडेट करने की आवश्यकता नहीं होती है।

इंटरफ़ेस अलगाव सिद्धांत और निर्भरता उलटा सिद्धांत के बाद हमें अत्यधिक लचीला, डिकोड किए गए अनुप्रयोगों का निर्माण करने की अनुमति देता है। एक बार जब आप इन प्रकार के अनुप्रयोगों में से किसी एक पर काम कर लेते हैं, तो आप फिर कभी newकीवर्ड का उपयोग करके वापस नहीं जाना चाहेंगे ।


40
SOLO के लिए IMO के कारखाने कम से कम महत्वपूर्ण हैं। आप बिना कारखानों के ही ठीक कर सकते हैं।
व्यंग्यात्मक

26
एक चीज जो मेरे लिए कभी मायने नहीं रखती है, अगर आप नई वस्तुओं को बनाने के लिए कारखानों का उपयोग करते हैं तो आपको पहली जगह में कारखाना बनाना होगा। तो वास्तव में क्या आपको मिलता है? क्या यह मान लिया जाता है कि कोई दूसरा आपको फैक्ट्री देने के बजाय आपको खुद ही इसे सौंप देगा, या कुछ और? इसका उत्तर में उल्लेख किया जाना चाहिए, अन्यथा यह स्पष्ट नहीं है कि कारखाने वास्तव में किसी समस्या को कैसे हल करते हैं।
मेहरदाद

8
@ B @овиЈ - इसके अलावा कि हर बार जब आप एक नया कार्यान्वयन जोड़ते हैं, तो आपको अब कारखाने को खोलने और नए कार्यान्वयन के लिए इसे संशोधित करने के लिए संशोधित करना होगा - स्पष्ट रूप से ओसीपी का उल्लंघन।
तेलस्टिन

6
@Telastyn हां, लेकिन बनाई गई वस्तुओं का उपयोग करने वाला कोड नहीं बदलता है। यह अधिक महत्वपूर्ण है तो कारखाने में परिवर्तन।
B34овиЈ

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

126

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

बात यह है कि, कारखानों (और एकल) को लागू करना बेहद आसान है और इसलिए लोग उन जगहों पर बहुत अधिक उपयोग करते हैं, यहां तक ​​कि उन जगहों पर भी जहां वे आवश्यक नहीं हैं। इसलिए जब प्रोग्रामर सोचता है "मुझे इस कोड में कौन से डिज़ाइन पैटर्न का उपयोग करना चाहिए?" फैक्ट्री सबसे पहले उसके दिमाग में आती है।

कई कारखाने बनाए जाते हैं क्योंकि "हो सकता है, एक दिन, मुझे उन वर्गों को अलग तरीके से बनाने की आवश्यकता होगी"। जो कि YAGNI का स्पष्ट उल्लंघन है ।

और जब आप IoC ढांचे का परिचय देते हैं तो कारखाने अप्रचलित हो जाते हैं, क्योंकि IoC एक तरह का कारखाना है। और कई आईओसी ढांचे विशिष्ट कारखानों के कार्यान्वयन बनाने में सक्षम हैं।

इसके अलावा, कोई भी डिज़ाइन पैटर्न नहीं है जो विशाल स्थिर कक्षाओं को बनाने के लिए कहता है, CreateXXXजो केवल रचनाकारों को बुलाते हैं। और इसे विशेष रूप से फैक्ट्री नहीं कहा जाता है (न ही सार फैक्ट्री)।


6
मैं आपके अधिकांश बिंदुओं से सहमत हूं "IoC कारखाने की तरह है" को छोड़कर : IoC कंटेनर कारखाने नहीं हैं । वे निर्भरता इंजेक्शन प्राप्त करने का एक सुविधाजनक तरीका है। हां, कुछ स्वचालित कारखानों का निर्माण करने में सक्षम हैं, लेकिन वे स्वयं कारखाने नहीं हैं और उन्हें ऐसा नहीं माना जाना चाहिए। मैं YAGNI बिंदु का भी विरोध करूंगा। यह उपयोगी है कि आपकी इकाई परीक्षा में टेस्ट डबल का विकल्प दिया जा सके। तथ्य के बाद यह प्रदान करने के लिए सब कुछ को फिर से भरना गधे में एक दर्द है । आगे की योजना बनाएं और "YAGNI" बहाने के लिए न पड़ें
AlexFoxGill

11
@AlexG - एह ... व्यवहार में, बहुत सारे IoC कंटेनर कारखानों के रूप में काम करते हैं।
तेलस्टीन

8
आईओसी का @AlexG प्राथमिक फोकस कॉन्फ़िगरेशन / कन्वेंशन के आधार पर अन्य वस्तुओं में पारित होने के लिए ठोस वस्तुओं का निर्माण करना है। यह कारखाने का उपयोग करने के समान है। और आपको परीक्षण के लिए नकली बनाने के लिए कारखाने की आवश्यकता नहीं है। आप बस तुरंत मॉक करें और सीधे मॉक पास करें। जैसा मैंने पहले पैराग्राफ में कहा था। फैक्ट्री केवल तब उपयोगी होती हैं जब आप मॉड्यूल के उपयोगकर्ता को एक उदाहरण के निर्माण को पारित करना चाहते हैं, जो कारखाने को कॉल करता है।
व्योम

5
वहाँ एक भेद किया जाना है। कारखाने पैटर्न एक कार्यक्रम के दौरान क्रम संस्थाओं बनाने के लिए एक उपभोक्ता द्वारा प्रयोग किया जाता है। स्टार्ट-अप के दौरान प्रोग्राम का ऑब्जेक्ट ग्राफ बनाने के लिए एक IoC कंटेनर का उपयोग किया जाता है। आप इसे हाथ से कर सकते हैं, कंटेनर सिर्फ एक सुविधा है। एक कारखाने के उपभोक्ता को आईओसी कंटेनर के बारे में पता नहीं होना चाहिए।
एलेक्सफॉक्सगिल

5
पुन: "और आपको परीक्षण के लिए मॉक बनाने में सक्षम होने के लिए कारखाने की आवश्यकता नहीं है। आप बस तुरंत मॉक करें और सीधे मॉक पास करें" - फिर से, विभिन्न परिस्थितियों। आप एक कारखाने का उपयोग एक उदाहरण का अनुरोध करने के लिए करते हैं - उपभोक्ता इस बातचीत के नियंत्रण में है। कंस्ट्रक्टर या एक विधि के माध्यम से एक उदाहरण देना काम नहीं करता है, यह एक अलग परिदृश्य है।
एलेक्सफॉक्सगिल

79

फ़ैक्टरी पैटर्न प्रचलन "सी-स्टाइल" भाषाओं (सी / सी ++, सी #, जावा) में कोडर्स के बीच एक लगभग-डोगमैटिक विश्वास से उपजा है कि "नया" कीवर्ड का उपयोग बुरा है, और हर कीमत (या) से बचा जाना चाहिए कम से कम केंद्रीकृत)। यह, बदले में, सिंगल रिस्पॉन्सिबिलिटी प्रिंसिपल (एसओएलआईडी के "एस") की अल्ट्रा-सख्त व्याख्या से आता है, और डिपेंडेंसी इन्वर्सेशन प्रिंसिपल ("डी") का भी। बस कहा गया है, एसआरपी कहता है कि आदर्श रूप से एक कोड ऑब्जेक्ट में एक "बदलने का कारण" होना चाहिए, और केवल एक; उस "कारण को बदलने" का उद्देश्य उस वस्तु का केंद्रीय उद्देश्य है, कोडबेस में इसकी "जिम्मेदारी", और कुछ और जो कोड में बदलाव की आवश्यकता है, उस वर्ग फ़ाइल को खोलने की आवश्यकता नहीं होनी चाहिए। डीआईपी और भी सरल है; एक कोड ऑब्जेक्ट को किसी अन्य ठोस वस्तु पर कभी भी निर्भर नहीं होना चाहिए,

बिंदु में, "नया" और एक सार्वजनिक निर्माणकर्ता का उपयोग करके, आप कॉलिंग कोड को एक विशिष्ट कंक्रीट क्लास के एक विशिष्ट निर्माण विधि से जोड़ रहे हैं। आपके कोड को अब यह जानना होगा कि एक वर्ग MyFooObject मौजूद है, और एक निर्माणकर्ता है जो एक स्ट्रिंग और एक इंट लेता है। यदि उस कंस्ट्रक्टर को कभी भी अधिक जानकारी की आवश्यकता होती है, तो कंस्ट्रक्टर के सभी उपयोगों को उस जानकारी में पास करने के लिए अपडेट किया जाना चाहिए, जिसमें आप अभी लिख रहे हैं, और इसलिए उन्हें पास होने के लिए कुछ वैध होना आवश्यक है, और इसलिए उन्हें या तो होना चाहिए इसे प्राप्त करने के लिए इसे बदला जा सकता है (खपत वस्तुओं में अधिक जिम्मेदारियों को जोड़ते हुए)। इसके अलावा, अगर MyFooObject को कभी भी BetterFooObject द्वारा कोडबेस में बदल दिया जाता है, तो पुराने वर्ग के सभी उपयोगों को पुराने के बजाय नई वस्तु के निर्माण के लिए बदलना होगा।

इसलिए, इसके बजाय, MyFooObject के सभी उपभोक्ताओं को सीधे "IFooObject" पर निर्भर होना चाहिए, जो MyFooObject सहित कक्षाओं को लागू करने के व्यवहार को परिभाषित करता है। अब, IFooObjects के उपभोक्ता केवल एक IFooObject का निर्माण नहीं कर सकते हैं (यह जानकर बिना कि एक विशेष ठोस वर्ग एक IFooObject है, जिसकी उन्हें आवश्यकता नहीं है), इसलिए इसके बजाय उन्हें एक IFooObject- कार्यान्वयन वर्ग या विधि का उदाहरण दिया जाना चाहिए। बाहर से, एक अन्य वस्तु से, यह जानने की ज़िम्मेदारी है कि परिस्थिति के लिए सही IFooObject कैसे बनाया जाए, जो कि हमारे प्रतिमान में आमतौर पर एक कारखाने के रूप में जाना जाता है।

अब, यहाँ जहाँ सिद्धांत वास्तविकता से मिलता है; एक वस्तु को हर समय सभी प्रकार के परिवर्तन के लिए बंद नहीं किया जा सकता है। बिंदु में मामला, IFooObject अब कोडबेस में एक अतिरिक्त कोड ऑब्जेक्ट है, जिसे उपभोक्ताओं द्वारा आवश्यक इंटरफ़ेस या IFooObjects के कार्यान्वयन में जब भी परिवर्तन होता है, बदलना होगा। यह इस अमूर्तता में एक दूसरे के साथ बातचीत करने के तरीके को बदलने में शामिल जटिलता के एक नए स्तर का परिचय देता है। इसके अलावा, उपभोक्ताओं को अभी भी बदलना होगा, और अधिक गहराई से, अगर इंटरफ़ेस खुद को एक नए द्वारा बदल दिया जाता है।

एक अच्छा कोडर जानता है कि कैसे SOLAG के साथ YAGNI ("यू ऐन गॉन नीड इट") को संतुलित करने के लिए, डिजाइन का विश्लेषण करके और उन स्थानों को ढूंढना है जो किसी विशेष तरीके से बदलने की संभावना रखते हैं, और उन्हें अधिक सहिष्णु होने के लिए फिर से तैयार कर रहे हैं। परिवर्तन के प्रकार, क्योंकि उस मामले में "आप कर रहे हैं वाला यह की जरूरत है"।


21
इस उत्तर को प्यार करें, विशेष रूप से अन्य सभी को पढ़ने के बाद। मैं लगभग सभी (अच्छे) नए कोडर्स को जोड़ सकता हूं सिद्धांतों के बारे में बहुत अधिक हठधर्मिता है सरल तथ्य यह है कि वे वास्तव में अच्छा होना चाहते हैं, लेकिन अभी तक चीजों को सरल रखने का मूल्य नहीं सीखा है और ओवरकिल नहीं करते हैं।
जीन

1
सार्वजनिक निर्माणकर्ताओं के साथ एक और समस्या यह है कि सार्वजनिक निर्माण Fooको निर्दिष्ट करने के लिए एक वर्ग के लिए कोई अच्छा तरीका नहीं है Fooउदाहरणों के निर्माण के लिए, या एक ही पैकेज / विधानसभा के भीतर अन्य प्रकारों के निर्माण के लिए उपयोग करने योग्य होना चाहिए, लेकिन निर्माण के लिए उपयोग करने योग्य नहीं होना चाहिए अन्य प्रकार से प्राप्त। मैं किसी विशेष रूप से सम्मोहक कारण के बारे में नहीं जानता / समझती हूं कि कोई भाषा / रूपरेखा newअभिव्यक्तियों में उपयोग के लिए अलग-अलग निर्माणकर्ताओं को परिभाषित नहीं कर सकती है , लेकिन उप-प्रकार निर्माणकर्ताओं से मंगलाचरण, लेकिन मैं किसी भी भाषा के बारे में नहीं जानता जो उस अंतर को बनाती है।
सुपरकैट

1
एक संरक्षित और / या आंतरिक निर्माता ऐसा संकेत होगा; यह कंस्ट्रक्टर केवल उप-कोड में या समान असेंबली के भीतर ही उपभोग कोड के लिए उपलब्ध होगा। C # में "संरक्षित और आंतरिक" के लिए कोई कीवर्ड संयोजन नहीं है, जिसका अर्थ है कि केवल विधानसभा के भीतर उप-भाग इसका उपयोग कर सकते हैं, लेकिन MSIL के पास उस प्रकार की दृश्यता के लिए एक स्कोप पहचानकर्ता है, इसलिए यह बोधगम्य है C # कल्पना का उपयोग करने के लिए एक तरीका प्रदान किया जा सकता है। । लेकिन, यह वास्तव में कारखानों के उपयोग के साथ बहुत कुछ नहीं करता है (जब तक कि आप कारखाने के उपयोग को लागू करने के लिए दृश्यता के प्रतिबंध का उपयोग नहीं करते हैं)।
कीथ

2
एकदम सही जवाब। 'सिद्धांत वास्तविकता से मिलता है' भाग के साथ सही बिंदु पर। जरा सोचिए कि हजारों डेवलपर्स और मानव समय ने कार्गो-पंथ की प्रशंसा करते हुए, न्यायोचित तरीके से, उन्हें लागू करते हुए, उसी स्थिति में गिरने का इस्तेमाल किया, जो आपके द्वारा बताई गई है। YAGNI के बाद, Ive ने कभी भी किसी कारखाने को लागू करने की आवश्यकता की पहचान नहीं की
Breno Salgado

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

33

जब वे छोटे, सरल कोड होते हैं, तो कंस्ट्रक्टर ठीक होते हैं।

जब इनिशियलाइज़ेशन कुछ वैरिएबल्स को खेतों में असाइन करने से अधिक हो जाता है, तो एक फैक्ट्री को समझ में आता है। यहाँ कुछ लाभ दिए गए हैं:

  • लंबे, जटिल कोड एक समर्पित वर्ग (एक कारखाने) में अधिक समझ में आता है। यदि समान कोड को एक कंस्ट्रक्टर में रखा जाता है, जो स्टैटिक विधियों का एक गुच्छा कहता है, तो यह मुख्य वर्ग को प्रदूषित करेगा।

  • कुछ भाषाओं और कुछ मामलों में, रचनाकारों में अपवादों को फेंकना वास्तव में एक बुरा विचार है , क्योंकि यह बग का परिचय दे सकता है।

  • जब आप एक निर्माता को आमंत्रित करते हैं, तो आपको, कॉलर को उस सटीक प्रकार को जानना होगा, जिसे आप बनाना चाहते हैं। यह हमेशा ऐसा नहीं होता है (एक के रूप में Feeder, मुझे Animalइसे खिलाने के लिए बस निर्माण करने की आवश्यकता है ; मुझे परवाह नहीं है कि यह Dogएक है Cat)।


2
विकल्प केवल "कारखाना" या "निर्माता" नहीं हैं। A Feederन तो उपयोग कर सकता है, और इसके बजाय इसे Kennelऑब्जेक्ट का getHungryAnimalतरीका कहता है ।
डगएम

4
+1, मुझे लगता है कि एक कंस्ट्रक्टर में बिल्कुल तर्क का पालन नहीं करना एक बुरा विचार नहीं है। एक कंस्ट्रक्टर का उपयोग केवल ऑब्जेक्ट की प्रारंभिक स्थिति को सेट करने के लिए किया जाना चाहिए, उदाहरणों के चर के लिए अपने तर्क मान निर्दिष्ट करके। यदि अधिक जटिल कुछ भी आवश्यक हो, तो कम से कम एक कारखाने (वर्ग) विधि का निर्माण करें ताकि उदाहरण बन सके।
KaptajnKold

यह एकमात्र संतोषजनक जवाब है जो मैंने यहां देखा है, मुझे अपना लिखने से बचाया। अन्य उत्तर केवल अमूर्त अवधारणाओं में काम कर रहे हैं।
TheCatWhisperer

लेकिन इस तर्क को भी सही माना जा सकता है Builder Pattern। है ना?
14

कंस्ट्रक्टर्स का शासन
ब्रेनो सालगाडो

10

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

एक सरल उदाहरण: आप एक उपकरण के साथ संवाद करना चाहते हैं, लेकिन आप यह नहीं जानते हैं कि यह ईथरनेट, COM या USB के माध्यम से होगा। आप एक इंटरफ़ेस और 3 कार्यान्वयन परिभाषित करते हैं। रनटाइम के दौरान आप चुन सकते हैं कि आपको कौन सी विधि चाहिए और कारखाना आपको उचित कार्यान्वयन देगा।

इसे अक्सर उपयोग करें ...


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

अब आपके पास जोड़ा गया लचीलापन है और सिद्धांत रूप में आपका एप्लिकेशन ईथरनेट, COM, USB और सीरियल का उपयोग कर सकता है, फायरलूप या सिद्धांत में जो भी हो, के लिए तैयार है। वास्तव में आपका ऐप केवल ईथरनेट पर ही संचार करेगा .... कभी भी।
पीटर बी

7

यह जावा / सी # के मॉड्यूल सिस्टम में एक सीमा का लक्षण है।

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

आप कर सकते हैं एक तरह से फाइल सिस्टम और संकलक विकल्प ताकि के साथ नगण्य द्वारा इस के आसपास पाने के com.example.Fooलिए एक अलग फाइल करने के लिए नक्शे, लेकिन यह आश्चर्य की बात है और unintuitive है। यदि आप ऐसा करते हैं, तो भी आपका कोड अभी भी कक्षा के केवल एक कार्यान्वयन से बंधा है। Ie यदि आप एक वर्ग लिखते हैं जो एक वर्ग Fooपर निर्भर करता है MySet, तो आप MySetसंकलन समय पर कार्यान्वयन का चयन कर सकते हैं, लेकिन आप अभी भी Fooदो अलग-अलग कार्यान्वयनों का उपयोग करके तुरंत नहीं कर सकते हैं MySet

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

बेशक, अगर आप कहते new Foo(...)हैं कि आपके पास अभी भी कक्षा पर निर्भरता है , तो आपको एक कारखाने की आवश्यकता है यदि आप चाहते हैं कि एक वर्ग सीधे एक इंटरफ़ेस को तुरंत सक्षम कर सके। हालांकि, यह आमतौर पर कंस्ट्रक्टर में उदाहरण को स्वीकार करने और किसी और को तय करने देता है कि किस कार्यान्वयन का उपयोग करना है।

यह तय करना है कि आप इंटरफेस और कारखानों के साथ अपने कोडबेस को खिलाने के लायक हैं या नहीं। एक ओर, यदि प्रश्न में वर्ग आपके कोडबेस के लिए आंतरिक है, तो कोड को फिर से भरना ताकि यह भविष्य में एक अलग वर्ग या एक इंटरफ़ेस का उपयोग करता है तुच्छ है; यदि स्थिति उत्पन्न होती है तो आप YAGNI और रिफ्लैक्टर को लागू कर सकते हैं । लेकिन यदि वर्ग आपके द्वारा प्रकाशित पुस्तकालय के सार्वजनिक एपीआई का हिस्सा है, तो आपके पास ग्राहक कोड तय करने का विकल्प नहीं है। यदि आप एक का उपयोग नहीं करते हैं interfaceऔर बाद में कई कार्यान्वयन की आवश्यकता है, तो आप एक चट्टान और एक कठिन जगह के बीच फंस जाएंगे।


2
काश जावा और डेरिवेटिव्स जैसे .NET में एक वर्ग के लिए एक विशेष वाक्यविन्यास होता है जो स्वयं का उदाहरण newबनाता है, और अन्यथा विशेष रूप से नामित स्थैतिक विधि को कॉल करने के लिए सिंटैक्टिक शुगर हो सकता है (जो कि एक प्रकार का "सार्वजनिक निर्माणकर्ता" होने पर स्वतः उत्पन्न होगा) "लेकिन स्पष्ट रूप से विधि शामिल नहीं है)। IMHO, यदि कोड केवल एक उबाऊ डिफ़ॉल्ट चीज चाहता है जो लागू करता है List, तो इंटरफ़ेस के लिए यह संभव होना चाहिए कि वह क्लाइंट के बिना किसी विशेष कार्यान्वयन (जैसे ArrayList) का पता लगाए बिना उसे दे सके ।
सुपरकैट

2

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

और जब से उन्होंने "हजारों CreateXXX स्थिर तरीकों के साथ एक विशाल कपड़े वर्ग" बनाया है, तो यह एक विरोधी पैटर्न (शायद एक भगवान वर्ग शायद?) लगता है।

मुझे लगता है कि सिंपल फैक्ट्री और स्टैटिक क्रिएटर तरीके (जिनमें बाहरी वर्ग की आवश्यकता नहीं है), कुछ मामलों में उपयोगी हो सकते हैं। उदाहरण के लिए, जब किसी वस्तु के निर्माण के लिए अन्य वस्तुओं (जैसे अनुकूल रचना) को प्रेरित करने जैसे विभिन्न चरणों की आवश्यकता होती है।

मैं फोन भी नहीं कर सकता कि एक कारखाना है, लेकिन सिर्फ "फैक्टरी" प्रत्यय के साथ कुछ यादृच्छिक वर्ग में समझाया तरीकों का एक गुच्छा।


1
सिंपल फैक्ट्री का अपना स्थान है। कल्पना कीजिए कि एक इकाई दो निर्माण मापदंडों को लेती है, int xऔर IFooService fooService। आप fooServiceहर जगह से गुजरना नहीं चाहते हैं , इसलिए आप एक विधि के साथ एक कारखाना बनाते हैं Create(int x)और कारखाने के अंदर सेवा को इंजेक्ट करते हैं।
एलेक्सफॉक्सगिल

4
@ एलेक्स जी और फिर, आपको IFactoryइसके बजाय हर जगह से गुजरना होगा IFooService
व्यंग्यात्मक

3
मैं व्यंजना से सहमत हूं; मेरे अनुभव में, उन वस्तुओं को, जो ऊपर से एक ग्राफ में इंजेक्ट होते हैं, एक प्रकार की होती हैं, जो सभी निचले स्तर की वस्तुओं की आवश्यकता होती है, और इसलिए IFooServices के आसपास से गुजरना कोई बड़ी बात नहीं है। एक दूसरे के साथ एक अमूर्त की जगह कुछ भी पूरा नहीं करता है, लेकिन आगे कोडबेस को आगे बढ़ाता है।
कीथ्स

यह पूछे गए प्रश्न के लिए पूरी तरह अप्रासंगिक लगता है, "मुझे प्रत्यक्ष वस्तु निर्माण के बजाय कारखाने वर्ग का उपयोग क्यों करना चाहिए? मुझे सार्वजनिक निर्माणकर्ताओं का उपयोग कब करना चाहिए, और मुझे कारखानों का उपयोग कब करना चाहिए?" देखें कैसे जवाब दें
gnat

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

1

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

एक पुस्तकालय के निर्माता के रूप में, यदि आप स्वयं उस लचीलेपन का उपयोग करना चाहते हैं तो आप कारखाने के तरीकों का उपयोग करेंगे।

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


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

-4

यह स्कैला और कार्यात्मक प्रोग्रामिंग के युग में अप्रचलित प्रतीत होता है। कार्यों का एक ठोस आधार एक गजिलियन वर्गों को प्रतिस्थापित करता है।

यह भी ध्यान दें कि जावा का डबल {{किसी कारखाने का उपयोग करते समय काम नहीं करता है

someFunction(new someObject() {{
    setSomeParam(...);
    etc..
}})

जो आपको एक अनाम वर्ग बनाने और उसे अनुकूलित करने की अनुमति दे सकता है।

टाइम स्पेस डिमेमा में टाइम फैक्टर अब फास्ट सीपीयू की बदौलत इतना सिकुड़ गया है कि स्पेस की सिकुड़न यानी कोड साइज को सक्षम करने वाली फंक्शनल प्रोग्रामिंग अब व्यावहारिक हो गई है।


2
यह एक स्पर्श-संबंधी टिप्पणी की तरह दिखता है (देखें उत्तर कैसे दें ), और इससे पहले किए गए बिंदुओं पर पर्याप्त कुछ भी नहीं दिया गया है और पहले 9 उत्तरों में समझाया गया है
gnat
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.