2009-05-08 18 views
6

कारखाने या साधारण फैक्ट्री को लागू करते समय, कक्षा को निर्दिष्ट करने के लिए कक्षा को निर्दिष्ट करने के बजाय एनम के बजाय टाइप का उपयोग करने के खिलाफ क्या होगा?फैक्टरी पैटर्न: Enums या प्रकार?

उदाहरण

public class SimpleFactory 
{ 
public static ITest Create(Type type) 
{ 
    if (type == typeof(ConcreteTest1)) 
    return new ConcreteTest1(); 
    if (type == typeof(ConcreteTest2)) 
    return new ConcreteTest2(); 

    throw new Exception("Invalid type"); 
} 
} 

उत्तर

15

एक enum के लिए उपयोग कर जिसका अर्थ है कि यह कम संभावना है कि उपयोगकर्ता असमर्थित प्रकार के साथ अपने कारखाने का उपयोग करने की कोशिश करेंगे है अधिक प्रतिबंधात्मक है,।

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

throw new Exception("Invalid type"); 

एक enum का उपयोग करते हुए इस को खत्म होगा: की अनुमति दे "प्रकार" इस ​​मामले में अपने कार्य को करने के तरीके कि में परिणाम होगा के लाखों लोगों को खोलता है। एक enum फेंकने का एकमात्र तरीका होगा अगर उपयोगकर्ता ने कुछ गलत तरीके से गलत किया।

+2

मैं निश्चित रूप से सहमत हूं! संकलन-समय की बाधाओं को लागू करने और उपयोग करने में आसान होने के लिए बहुत आसान है। – jeremyalan

2

यदि आप मूर्ख प्रमाण कारखाना चाहते हैं तो आपको प्रत्येक ठोस प्रकार के लिए एक ठोस कारखाना बनाना होगा। यह वर्ग खुले बंद सिद्धांत का पालन नहीं करता है: हर बार जब आपको एक नया ठोस प्रकार मिल जाता है तो आपको इस कक्षा को दोबारा संपादित करना होगा।

आईएमएचओ एक बेहतर दृष्टिकोण विरासत का उपयोग कर रहा है, प्रत्येक ठोस प्रकार के लिए एक ठोस कारखाना वर्ग।

+0

आप कैसे तय करते हैं कि किस ठोस कारखाने का उपयोग करना है? आपको अभी भी उपरोक्त सशर्त की आवश्यकता होगी? – theringostarrs

+0

यदि आप फैक्ट्रीलोडर प्रकार श्रेणी का उपयोग करते हैं, जिसमें उपरोक्त सशर्त होते हैं ताकि ठोस कारखानों से तर्क हटा दिया जा सके, फैक्ट्रीलोडर तर्क में एक नया सशर्त/प्रकार का कारखाना जोड़ने के दौरान खुले/बंद सिद्धांत का उल्लंघन कैसे करें? क्या हम सिर्फ समस्या को कहीं और नहीं ले जा रहे हैं? – theringostarrs

+0

मुझे लगता है कि एक आईओसी कंटेनर इसका ख्याल रखेगा, लेकिन आप इसे शुद्ध तरीके से कैसे करेंगे? – theringostarrs

1

यदि आप प्रकार के अनुसार बनाना चाहते हैं, तो आप केवल Activator.CreateInstance(Type t) का उपयोग कर सकते हैं। इसे अपने इंटरफ़ेस तक सीमित करने के लिए टेम्पलेट विधि में लपेटें, Create<T> where T:ITest जैसे कुछ।

2

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

मैं जेनिक्स का उपयोग कर सी # में एक उदाहरण दूंगा।

public class SimpleFactory 
{ 
public static ITest Create<T>() 
    where T: ITest, new() 
{ 
    return new T(); 
} 
} 

तो फिर तुम दोनों ConcreteTest1 और ConcreteTest2 साथ IConcreteTest लागू करेगा और आप इस तरह अपने कारखाने इस्तेमाल कर सकते हैं:

ConcreteTest1 test1 = SimpleFactory.Create<ConcreteTest1>(); 
+0

किसी सामान्य विधि को टाइप करने से समस्या को ठीक कैसे किया जाता है? क्या अभी भी कॉलर द्वारा टी के कुछ उन्नत ज्ञान की आवश्यकता नहीं है? – jeremyalan

+0

हां, लेकिन उसके उदाहरण में वह पहले से ही जानता है, वह इसे विधि में पास कर रहा है। केवल अंतर यह है कि मैं इसे सामान्य के रूप में उपयोग कर रहा हूं ताकि आप SimpleFactory.Create () जैसे कुछ कर सकें; – Joseph

+0

उन्होंने टाइपऑफ के कार्यान्वयन को नहीं दिया है, इसलिए हम यह सुनिश्चित नहीं कर सकते कि उनके पास प्रकारों का अग्रिम ज्ञान है और कॉल में प्रवेश कर सकते हैं। – Rohit

1

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

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

मुझे लगता है कि कोई तर्क दे सकता है कि प्रकार का नाम कॉन्फ़िगरेशन फ़ाइल, डेटाबेस इत्यादि से स्ट्रिंग के रूप में पढ़ा जा सकता है, और प्रतिबिंब (.NET में) या RTTI (C++ में) का उपयोग करके निर्धारित प्रकार की जानकारी, लेकिन मुझे लगता है कि यह आपके पहचानकर्ता के रूप में टाइप स्ट्रिंग का उपयोग करने के लिए एक बेहतर मामला है क्योंकि यह प्रभावी रूप से उसी उद्देश्य को पूरा करेगा।

4

फैक्ट्री केवल तभी उपयोगी होती हैं जब वे आपके ऑब्जेक्ट्स पर कॉन्फ़िगरेशन या प्रारंभिक स्थिति को वैध स्थिति में डाल दें। मैं कारखाने से परेशान नहीं होता अगर यह सब नया होता है और ऑब्जेक्ट लौटाता है।

मैं प्रत्येक श्रेणी पदानुक्रम के लिए एक कारखाना तैयार करूंगा। उदाहरण के लिए:

public abstract class Vehicle {} 
public class Car : Vehicle {} 
public class Truck : Vehicle {} 

public class VehicleFactory 
{ 
    public Vehicle CreateVehicle<T>() where T : Vehicle 
    { 
     // Get type of T and delegate creation to private methods 
    } 
} 
संबंधित मुद्दे