2012-07-04 9 views
5

ठीक है, मैं this एमएसडीएन पर उत्कृष्ट लेख "बेस क्लास उपयोग" के बारे में जा रहा था। जबकि मैं बेस क्लास और इंटरफेस की अवधारणा को समझता हूं, मैं इस आलेख के दूसरे पैराग्राफ में टेम्पलेट विधियों के उपयोग को समझने में असमर्थ हूं ("संरक्षित तरीके और निर्माता")।बेस क्लासेस में टेम्पलेट विधि का उपयोग क्या है?

क्या कोई साधारण व्यावहारिक उदाहरण की मदद से मुझे इस अवधारणा को समझने में मदद कर सकता है? शायद, टेम्पलेट विधि की अवधारणा को समझना शुरू करने के लिए एक अच्छी जगह है।

अग्रिम धन्यवाद।

उत्तर

2

मेरी राय में बहुत पुराने लेख है, Impl साथ नामकरण देखकर याद नहीं है।

मुझे लगता है कि विकिपीडिया बेहतर विवरण नहीं है:

  • उपवर्गों व्यवहार है कि कोड में

  • से बचने के दोहराव से भिन्न हो सकते हैं (विधि अधिभावी के माध्यम से) को लागू करते हैं:
    टेम्पलेट विधि करने के लिए प्रयोग किया जाता है: सामान्य वर्कफ़्लो संरचना को अमूर्त वर्ग के एल्गोरिदम में एक बार लागू किया जाता है, और प्रत्येक उप-वर्ग में आवश्यक विविधताएं लागू की जाती हैं।

  • किस बिंदु (ओं) उपclassing पर नियंत्रण की अनुमति है। एक साधारण पॉलीमोर्फिक ओवरराइड के विपरीत, जहां बेस विधि पूरी तरह से वर्कफ़्लो में कट्टरपंथी परिवर्तन की इजाजत दे दी जाएगी, केवल वर्कफ़्लो के विशिष्ट विवरण बदलने की अनुमति है।

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

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

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

public abstract class Publisher 
{ 
     private address; 
     // if you wish to force implementation in derived class, make method abstract 
     private abstract void Initialize(); 
     // if you wish optional implementation in derived class, make it virtual 
     protected virtual void SendChangesToWeb() 
     { 
     // ... 
     webClient.Upload(address, data) 
     } 

     // if you wish that some step could not be changed from outside 
     private void LogSentChangesToDatabase() 
     { 
     // ... save date time when was send and what was sent 
     } 

     // this sequence is the same for all derives, no point to duplicate 
     public void PublishUpdates() 
     { 
      Initialize(); 
      SendChangesToWeb(); 
      LogSentChangesToDatabase(); 
     } 
} 

public class GooglePublisher : Publisher { 
    private override Initialize() 
    { 
     address = "http://www.google.com"; 
    }   
} 

public class FtpPublisher : Publisher { 
    private override Initialize() 
    { 
     address = "ftp://test.com"; 
    }  

    protected override SendChangesToWeb() 
    { 
     FtpClient.Upload(address, data) 
    } 
} 
+0

धन्यवाद Giedrius, यह एक बहुत ही जानकारीपूर्ण उदाहरण है। मुझे लगता है कि मुझे वास्तव में इस अवधारणा का कुछ समझ है। लेकिन मुझे नहीं पता कि यह अधिक ड्रिल करने योग्य है या यदि कोई इस शैली का व्यावहारिक दुनिया में उपयोग कर रहा है। – Aakash

+0

नामकरण शैली - नहीं, लेकिन पैटर्न का उपयोग किया जाता है, उपयोगी और काफी प्राकृतिक (प्राकृतिक - मेरा मतलब है कि मैं यह जानने के बिना इसका उपयोग कर रहा था कि यह एक प्रसिद्ध पैटर्न है :)। – Giedrius

+0

:-) शायद मैंने यह नहीं देखा। हालांकि यह सरल और साफ है। आपकी सभी मदद का धन्यवाद। – Aakash

1

विचार यह है कि आपके पास एक विधि के कई सार्वजनिक ओवरलोड हैं जो सभी आंतरिक रूप से एक विधि का उपयोग करते हैं। इसलिए सार्वजनिक ओवरलोड में से कोई भी कार्यान्वयन स्वयं ही नहीं है। इसके बजाय सभी अधिभारों के वास्तविक कार्यान्वयन के लिए एक संरक्षित विधि का उपयोग किया जाता है।

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

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

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

+0

धन्यवाद !, इस विशेष मामले में, सार्वजनिक विधि से कार्यान्वयन को अलग करने के लिए ड्राइविंग कारक को छिपाने वाली जानकारी है। (संरचना/वर्कफ़्लो को समान रखने के अलावा।) अगर मैं इसे सही ढंग से समझता हूं, तो मुझे लगता है कि यह एक बहुत अच्छा प्रोग्रामिंग निर्माण है। अब मैं सोच रहा हूं कि इस पैटर्न का उपयोग करने के नुकसान क्या हो सकते हैं। – Aakash

0

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

// Template Method pattern -- Structural example 

using System; 



namespace DoFactory.GangOfFour.Template.Structural 

{ 

    /// <summary> 

    /// MainApp startup class for Real-World 

     /// Template Design Pattern. 

     /// </summary> 

     class MainApp 

    { 

    /// <summary> 

    /// Entry point into console application. 

    /// </summary> 

    static void Main() 

    { 

     AbstractClass aA = new ConcreteClassA(); 

     aA.TemplateMethod(); 



     AbstractClass aB = new ConcreteClassB(); 

     aB.TemplateMethod(); 



     // Wait for user 

     Console.ReadKey(); 

    } 

    } 



    /// <summary> 

    /// The 'AbstractClass' abstract class 

    /// </summary> 

    abstract class AbstractClass 

    { 

    public abstract void PrimitiveOperation1(); 

    public abstract void PrimitiveOperation2(); 



    // The "Template method" 

    public void TemplateMethod() 

    { 

     PrimitiveOperation1(); 

     PrimitiveOperation2(); 

     Console.WriteLine(""); 

    } 

    } 



    /// <summary> 

    /// A 'ConcreteClass' class 

    /// </summary> 

    class ConcreteClassA : AbstractClass 

    { 

    public override void PrimitiveOperation1() 

    { 

     Console.WriteLine("ConcreteClassA.PrimitiveOperation1()"); 

    } 

    public override void PrimitiveOperation2() 

    { 

     Console.WriteLine("ConcreteClassA.PrimitiveOperation2()"); 

    } 

    } 



    /// <summary> 

    /// A 'ConcreteClass' class 

    /// </summary> 

    class ConcreteClassB : AbstractClass 

    { 

    public override void PrimitiveOperation1() 

    { 

     Console.WriteLine("ConcreteClassB.PrimitiveOperation1()"); 

    } 

    public override void PrimitiveOperation2() 

    { 

     Console.WriteLine("ConcreteClassB.PrimitiveOperation2()"); 

    } 

    } 

} 

संदर्भ: Template Method Design Pattern

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