कारखानों के रूप में बेस क्लास?


14

मैं सप्ताहांत में कुछ कोड लिख रहा था और मैंने खुद को एक बेस क्लास में एक स्थिर विधि के रूप में एक कारखाना लिखना चाहा।

मेरा सवाल बस यह जानना है कि क्या यह एसी # मुहावरेदार तरीका है?

मेरी समझ से यह नहीं हो सकता है कि आधार वर्ग को व्युत्पन्न वर्ग का ज्ञान है।

उस ने कहा, मैं एक ही परिणाम प्राप्त करने के लिए एक सरल तरीका सुनिश्चित नहीं हूं। एक पूरी दूसरी फैक्ट्री क्लास लगती है (कम से कम मुझे) गैर-जरूरी जटिलता (?) की तरह

कुछ इस तरह:

class Animal
{
  public static Animal CreateAnimal(string name)
  {
     switch(name)
     {
        case "Shark":
          return new SeaAnimal();
          break;
        case "Dog":
          return new LandAnimal();
          break;
        default:
          throw new Exception("unknown animal");
     }
  }
}
class LandAnimal : Animal
{
}

class SeaAnimal : Animal
{
}

आप अपने कारखानों का परीक्षण कैसे करेंगे?

इस प्रश्न में कोड के साथ, मैं नहीं करूंगा। लेकिन जवाब ने मुझे मेरी कोडिंग शैली में और अधिक परीक्षण को एकीकृत करने के मार्ग में मदद की है
हारून एनोडाइड

विचार करें कि आपके पशु वर्ग में सीवर्ल्ड और लैंडवर्ल्ड दोनों में खींच लिया गया है, सभी को एक अलग सेटिंग में संभालना मुश्किल है।

जवाबों:


13

खैर, एक अलग कारखाना वर्ग का लाभ यह है कि इसे इकाई परीक्षणों में नकली किया जा सकता है।

लेकिन अगर आप ऐसा नहीं करने जा रहे हैं, या इसे किसी अन्य तरीके से बहुरूपी बना रहे हैं, तो कक्षा पर एक स्थिर फैक्टरी विधि ही ठीक है।


धन्यवाद, क्या आप इस बात का उदाहरण दे सकते हैं कि जब आप पॉलिमॉर्फिक को किसी अन्य तरीके से कहते हैं तो आप क्या कर रहे हैं?
हारून एनोडाइड

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

18

आप स्विच स्टेटमेंट से बचने और बेस क्लास से डाउनस्ट्रीम कार्यान्वयन को कम करने के लिए जेनरिक का उपयोग कर सकते हैं:

 public static T CreateAnimal<T>() where T: new, Animal
 {
    return new T();
 }

उपयोग:

LandAnimal rabbit = Animal.CreateAnimal();  //Type inference should should just figure out the T by the return indicated.

या

 var rabbit = Animal.CreateAnimal<LandAnimal>(); 


2
@PeterK। फाउलर कोड गंध में बयान स्विच करने के लिए संदर्भित करता है, लेकिन उसका समाधान यह है कि उन्हें प्रतिस्थापित करने के बजाय फैक्ट्री कक्षाओं में निकाला जाना चाहिए। कहा कि, यदि आप हमेशा विकास के समय प्रकार जानते हैं, तो जेनेरिक एक बेहतर समाधान है। लेकिन यदि आप (मूल उदाहरण के रूप में निहित) नहीं करते हैं, तो मैं तर्क दूंगा कि कारखाने की विधि में स्विच से बचने के लिए प्रतिबिंब का उपयोग करना झूठी अर्थव्यवस्था हो सकती है।
पीडीआर

स्विच स्टेटमेंट्स और if-else-if चेन समान हैं। मैं संकलित समय की जाँच के कारण पूर्व का उपयोग करता हूं जो डिफ़ॉल्ट मामले को संभालने के लिए मजबूर करता है
हारून एनोडाइड

4
@PeterK, एक स्विच स्टेटमेंट में कोड एक ही स्थान पर है। पूर्ण विकसित OO में एक ही कोड कई, अलग-अलग वर्गों में फैलाया जा सकता है। एक ग्रे क्षेत्र है जहां कई स्निपेट होने की गयी जटिलता स्विच-स्टेटमेंट की तुलना में कम वांछनीय है।

@ थोरबॉर्न, मुझे लगता है कि सटीक सोचा था, लेकिन कभी इतनी
गंभीरता से

5

चरम पर ले जाया गया, कारखाना सामान्य भी हो सकता है।

interface IFactory<K, T> where K : IComparable
{
    T Create(K key);
}

फिर कोई भी किसी भी प्रकार की वस्तुओं का कारखाना बना सकता है, जो बदले में किसी भी प्रकार की वस्तु का निर्माण कर सकता है। मुझे यकीन नहीं है कि अगर यह आसान है, तो यह निश्चित रूप से अधिक सामान्य है।

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


1

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

यदि आपको किसी कॉन्फ़िगरेशन से जानवरों को बनाने की आवश्यकता है, तो इस तरह का एक निर्माण ठीक होगा, हालांकि नाम से मेल खाने वाले प्रकार को प्राप्त करने के लिए प्रतिबिंब का उपयोग करना और उस प्राप्त प्रकार की जानकारी का उपयोग करके इसे तुरंत बेहतर विकल्प होगा।

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


0

यह सवाल मेरे लिए समय पर है - मैं कल लगभग ऐसे ही कोड लिख रहा था। मेरी परियोजना में जो भी प्रासंगिक है, उसके साथ "पशु" को बदलें, हालांकि मैं यहां चर्चा के लिए "पशु" के साथ रहूंगा। 'स्विच' स्टेटमेंट के बजाय, मेरे पास 'if' स्टेटमेंट्स की कुछ अधिक जटिल सीरीज़ थीं, जिनमें एक वेरिएबल की तुलना कुछ निश्चित मानों से अधिक थी। लेकिन यह एक विस्तार है। एक स्थिर फैक्टरी विधि चीजों को डिजाइन करने के लिए एक साफ तरीके की तरह लग रहा था, जैसा कि डिजाइन कोड के पहले त्वरित-और-गंदे गंदगी को फिर से बनाने से उभरा था।

मैंने इस डिजाइन को आधार वर्ग के आधार पर खारिज कर दिया, जिसमें व्युत्पन्न वर्ग का ज्ञान था। यदि कक्षाएं LandAnimal और SeaAnimal छोटी, साफ और आसान हैं, तो वे एक ही स्रोत फ़ाइल में हो सकती हैं। लेकिन मेरे पास किसी भी आधिकारिक रूप से परिभाषित मानकों के अनुरूप नहीं होने वाली पाठ फ़ाइलों को पढ़ने के लिए बड़ी गन्दी विधियाँ हैं - मैं चाहता हूँ कि मेरा LandAnimal वर्ग इसके अन्य स्रोत फ़ाइल में हो।

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

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

इसके अलावा, मुझे नहीं पता कि भविष्य के काम में विस्तारित होने की संभावना छोटे, सरल वर्गों के मामले में स्थिर कारखाना विधि का उपयोग करने का कोई फायदा होगा - यह सब एक स्रोत फ़ाइल में होने से कुछ मामलों में अच्छा हो सकता है।

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