2012-10-29 10 views
5

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

तो मेरा पहला प्रयास उन दो प्रक्रियाओं को अपने स्वयं के वर्गों में निकालने और सामान्य कोड को उन माता-पिता में डालने के लिए किया गया है, जिन्हें वे दोनों प्राप्त करते हैं।

public class ExportProcess 
{ 
    public ExportClass(IExportDataProvider dataProvider, IExporterFactory exporterFactory) 
    { 
     _dataProvider = dataProvider; 
     _exporterFactory = exporterFactory; 
    } 

    public void DoExport(SomeDataStructure someDataStructure) 
    { 
     _dataProvider.Load(someDataStructure.Id); 

     var exporter = _exporterFactory.Create(_dataProvider, someDataStructure); 

     exporter.Export(); 
    } 
} 

मैं मार्क सीनैन के ब्लॉग का एक उत्साही पाठक हूं और this entry में वे बताते हैं इस कोड को एक अस्थायी युग्मन गंध है के बाद से यह आवश्यक है पर लोड विधि कॉल करने के:

यह कुछ इस तरह दिखता इससे पहले डेटा प्रदाता एक उपयोगी राज्य में है।

उस आधार पर, और के बाद से वस्तु वैसे भी कारखाना द्वारा लौटाए गए लोगों के इंजेक्शन की जा रही है, मैं कारखाने से बदल रहा यह करने के लिए की सोच रहा हूँ:

public IExporter Create(IExportDataProvider dataProvider, SomeDataStructure someDataStructure) 
{ 
    dataProvider.Load(someDataStructure.Id); 

    if(dataProvider.IsNewExport) 
    { 
     return new NewExportExporter(dataProvider, someDataStructure); 
    } 
    return new UpdateExportExporter(dataProvider, someDataStructure); 
} 
नाम की वजह से

"dataProvider" आप शायद अनुमान लगाया गया है कि लोड विधि वास्तव में डेटाबेस पहुंच कर रही है।

कुछ मुझे बताता है कि एक सार कारखाने के निर्माण विधि के अंदर डेटाबेस पहुंच करने वाला कोई ऑब्जेक्ट एक अच्छा डिज़ाइन नहीं है।

क्या कोई दिशानिर्देश, सर्वोत्तम प्रथाएं या कुछ ऐसा कहता है जो प्रभावी रूप से एक बुरा विचार है?

आपकी मदद के लिए धन्यवाद।

+0

जाहिर dataProvider.Load पक्ष प्रभाव के कुछ प्रकार है, एक संपत्ति में कुछ का एक उदाहरण प्राप्त करने में कठिनाई की तर्ज पर? क्या बाकी फैक्ट्री-विधि वास्तव में 'डेटाप्रोवाइडर' और 'कुछ डेटा संरचना' का उपयोग करती है? यदि ऐसा नहीं होता है, तो फैक्ट्री-विधि के लिए आपके तर्कों को वास्तव में आवश्यक तर्कों को स्वीकार करने में दोबारा प्रतिक्रिया दी जानी चाहिए। – PatrikAkerstrand

+0

@PatrikAkerstrand: अच्छा बिंदु Patrik। कारखाने द्वारा बनाए गए ऑब्जेक्ट्स वास्तव में डेटा प्रदाता का भारी उपयोग करते हैं क्योंकि इसकी लोड विधि आवश्यक कुछ गुणों को पॉप्युलेट करती है। यह एक बहुत पहले रिफैक्टरिंग प्रयास है, लेकिन दुर्भाग्यवश यह तकनीकी ऋण का एक टुकड़ा है जिसे कम रन में भुगतान नहीं किया जा सकता है। –

+0

ठीक है, तो इस पर विचार करें: यदि DataProvider.Load को कई बार बुलाया जाएगा, तो क्या इससे कोई समस्या आएगी? ** यदि नहीं **: कूल, मैं 'लोड'-कॉल को फ़ैक्टरी विधि में ले जाऊंगा क्योंकि यह ग्राहकों को सरल बना देगा (सभी कॉल। फैक्टरी विधि के अंदर होंगी)। ** यदि हां **: आपके पास कारखाने के बाहर रखने के अलावा कोई विकल्प नहीं है, क्योंकि आप यह नहीं जान सकते कि यह प्रारंभ किया गया है या नहीं – PatrikAkerstrand

उत्तर

2

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

कारखाने का एक और अच्छा उपयोग उपभोक्ता प्रकार की निर्भरताओं से छिपाना है जो उपभोक्ता के लिए प्रासंगिक नहीं हैं। उदाहरण के लिए, ऐसा लगता है कि IExportDataProvider केवल आंतरिक रूप से प्रासंगिक है, और इसे उपभोक्ताओं से दूर किया जा सकता है (जैसे ExportProcess)।

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

public interface IExporterFactory 
{ 
    IExporter Create(SomeDataStructure someData); 
} 

public class MyConcreteExporterFactory : IExporterFactory 
{ 
    public MyConcreteExporterFactory(IExportDataProvider provider) 
    { 
      if (provider == null) throw new ArgumentNullException(); 

      Provider = provider; 
    } 

    public IExportDataProvider Provider { get; private set; }  

    public IExporter Create(SomeDataStructure someData) 
    { 
     var providerData = Provider.Load(someData.Id); 

     // do whatever. for example... 
     return providerData.IsNewExport ? new NewExportExporter(providerData, someData) : new UpdateExportExporter(providerData, someData); 
    } 
} 

और फिर उपभोग:

public class ExportProcess 
{ 
    public ExportProcess(IExporterFactory exporterFactory) 
    { 
     if (exporterFactory == null) throw new ArgumentNullException(); 

     _exporterFactory = factory; 
    } 

    private IExporterFactory _exporterFactory; 

    public void DoExport(SomeDataStructure someData) 
    { 
     var exporter = _exporterFactory.Create(someData); 
     // etc. 
    } 
} 
+0

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

+1

@SergioRomero उस मामले में, आप एक एडाप्टर पर विचार कर सकते हैं। कारखाने को आपके लिए आवश्यक आईईक्सपोर्टर के प्रकार को हल करने के लिए उपयोग करने दें, और वास्तव में आईईक्सपोर्टर के निर्माण को दलाल करने के लिए एडाप्टर का उपयोग करें। मैं देखूंगा कि क्या मैं अपना जवाब किसी उदाहरण के साथ अपडेट कर सकता हूं। – HackedByChinese

संबंधित मुद्दे