ब्रिज डिजाइन पैटर्न को समझना


24

मुझे "ब्रिज" डिज़ाइन पैटर्न बिल्कुल भी समझ नहीं आता है। मैं विभिन्न वेब साइटों से गुजरा हूं, लेकिन उन्होंने मदद नहीं की है।

क्या कोई इसे समझने में मेरी मदद कर सकता है?


2
मुझे यह समझ में नहीं आता है। जवाब देखने के लिए आगे देख रहे हैं :)
वायलेट जिराफ

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

जवाबों:


16

ओओपी में हम बहुरूपता का उपयोग करते हैं इसलिए एक अमूर्त में कई कार्यान्वयन हो सकते हैं। आइए निम्नलिखित उदाहरण देखें:

//trains abstraction
public interface Train
{ 
    move();
}
public class MonoRail:Train
{
    public override move()
    {
        //use one track;
    }
}
public class Rail:Train
{
    public override move()
    {
        //use two tracks;
    }
}

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

    public interface Train
    { 
        void move();
    }
    public class MonoRail:Train
    {
        public override void move()
        {
            //use one track;
        }
    }
    public class ElectricMonoRail:MonoRail
    {
        public override void move()
        {
            //use electric engine on one track.
        }
    }
    public class DieselMonoRail: MonoRail
    {
        public override void move()
        {
            //use diesel engine on one track.
        }
    }
    public class Rail:Train
    {
        public override void move()
        {
            //use two tracks;
        }
    }
    public class ElectricRail:Rail
    {
        public override void move()
        {
            //use electric engine on two tracks.
        }
    }
    public class DieselRail: Rail
    {
        public override void move()
        {
            //use diesel engine on two tracks.
        }
    }

उपरोक्त कोड कायम नहीं है और पुन: प्रयोज्यता का अभाव है (यह मानते हुए कि हम एक ही ट्रैक प्लेटफॉर्म के लिए त्वरण तंत्र का पुन: उपयोग कर सकते हैं)। निम्न कोड पुल पैटर्न को लागू करता है और दो अलग-अलग सार, ट्रेन परिवहन और त्वरण को अलग करता है

public interface Train
{ 
    void move(Accelerable engine);
}
public interface Accelerable
{
    public void accelerate();
}
public class MonoRail:Train
{
    public override void move(Accelerable engine)
    {
        //use one track;
        engine.accelerate(); //engine is pluggable (runtime dynamic)
    }
}
public class Rail:Train
{
    public override void move(Accelerable engine)
    {
        //use two tracks;
        engine.accelerate(); //engine is pluggable (runtime dynamic)
    }
}
public class ElectricEngine:Accelerable{/*implementation code for accelerable*/}
public class DieselEngine:Accelerable{/*implementation code for accelerable*/}

3
बहुत अच्छा उदाहरण है। मैं अपने दो सेंट
जोड़ूंगा

1
इसके लायक क्या है, मुझे लगता है कि यह होना चाहिए Monorailक्योंकि यह वास्तव में दो शब्द नहीं है, यह एक एकल (यौगिक) शब्द है। एक मोनो रेल एक अलग तरह की रेल (जो यह है) के बजाय रेल का कुछ उपवर्ग होगा। जैसे हम उपयोग नहीं करेंगे SunShineया CupCake, वे होंगे SunshineऔरCupcake
ErikE

यह रेखा "दो अलग-अलग सार, ट्रेन परिवहन और त्वरण" में मदद करती है, इंगित करती है कि दो पदानुक्रम क्या हैं और हम जो हल करने की कोशिश करते हैं, उन्हें स्वतंत्र रूप से अलग करना है।
वाँगडक

11

जबकि अधिकांश डिज़ाइन पैटर्न में सहायक नाम होते हैं, मुझे लगता है कि "ब्रिज" नाम गैर-सहज ज्ञान युक्त है जो इसे करता है।

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

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

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

यहाँ एक वास्तविक दुनिया उदाहरण है:

मेरे पास एक RAD उपकरण है जो आपको एक डिज़ाइन सतह पर नियंत्रण को छोड़ने और कॉन्फ़िगर करने देता है, इसलिए मेरे पास इस तरह एक ऑब्जेक्ट मॉडल है:

Widget // base class with design surface plumbing
+ Top
+ Left
+ Width
+ Height
+ Name
+ SendToBack
+ BringToFront
+ OnPropertyEdit
+ OnSelect
+ Validate
+ ShowEditor
+ Paint
+ Etc

TextboxWidget : Widget // text box specific
+ Text
+ MaxLength
+ Font
+ ShowEditor // override base to show a property editor form specific to a Textbox
+ Paint // override to render a textbox onto the surface    
+ Etc

ListWidget : Widget // list specific
+ Items
+ SelectedItem
+ ShowEditor // override base to show a property editor form specific to a List
+ Paint // override to render a list onto the surface
+ Etc

और इतने पर, शायद एक दर्जन नियंत्रणों के साथ।

लेकिन फिर कई विषयों (लुक-एन-फील) का समर्थन करने के लिए एक नई आवश्यकता जोड़ी जाती है। मान लीजिए कि हम निम्न विषयों करते हैं: Win32, WinCE, WinPPC, WinMo50, WinMo65। प्रत्येक विषय में डिफॉल्टोंट, डिफॉल्ट बैकऑर्डर, बॉर्डरविद, ड्रॉफ्रेम, ड्रास्क्रोल ट्रम्ब आदि जैसे रेंडरिंग-संबंधित ऑपरेशंस के लिए अलग-अलग मूल्य या कार्यान्वयन होंगे।

मैं इस तरह एक वस्तु मॉडल बना सकता है:

Win32TextboxWidget : TextboxWidget

Win32ListWidget : ListWidget

आदि, एक नियंत्रण प्रकार के लिए

WinCETextboxWidget : TextboxWidget

WinCEListWidget : ListWidget

आदि, एक दूसरे के नियंत्रण प्रकार के लिए (फिर से)

आप विचार प्राप्त करते हैं - आपको विषयों के # बार # विजेट का # वर्ग विस्फोट होता है। यह RAD डिज़ाइनर को प्रत्येक विषय के बारे में अवगत कराते हुए जटिल बनाता है। साथ ही, नए विषयों को जोड़ने से आरएडी डिजाइनर को संशोधित किया जा सकता है। इसके अलावा, एक विषय के भीतर बहुत सारे सामान्य कार्यान्वयन हैं जो विरासत में प्राप्त करना बहुत अच्छा होगा, लेकिन नियंत्रण पहले से ही एक सामान्य आधार ( Widget) से विरासत में मिल रहे हैं ।

इसलिए इसके बजाय मैंने जो किया वह एक अलग वस्तु पदानुक्रम है जो थीम को लागू करता है। प्रत्येक विजेट उस ऑब्जेक्ट का संदर्भ रखेगा जो रेंडरिंग ऑपरेशंस को लागू करता है। कई ग्रंथों में, यह वर्ग एक प्रत्यय से भरा है, Implलेकिन मैं उस नामकरण सम्मेलन से भटक गया।

तो अब मेरा TextboxWidgetऐसा दिखता है:

TextboxWidget : Widget // text box specific
+ Text
+ MaxLength
+ Font
+ ShowEditor
+ Painter // reference to the implementation of the widget rendering operations
+ Etc

और मैं अपने विभिन्न चित्रकारों को अपने विषय-विशिष्ट आधार को प्राप्त कर सकता हूं, जो मैं पहले नहीं कर सकता था:

Win32WidgetPainter
+ DefaultFont
+ DefaultFontSize
+ DefaultColors
+ DrawFrame
+ Etc

Win32TextboxPainter : Win32WidgetPainter

Win32ListPainter : Win32WidgetPainter

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


मुझे समझ नहीं आ रहा है कि यह ब्रिज पैटर्न कैसे माना जाता है? जब आप विजेट पदानुक्रम में एक नया घटक जोड़ते हैं, तो आपको उस नए विजेट को सभी चित्रकारों (Win32NewWidgetPainter, PPCNewWidgetPainter) में जोड़ने के लिए मजबूर किया जाता है। यह दो स्वतंत्र रूप से बढ़ती पदानुक्रम नहीं है। एक उचित ब्रिज पैटर्न के लिए, आप प्रत्येक विजेट के लिए PlatformWidgetPainter वर्ग को उप-वर्ग नहीं करेंगे, बल्कि इसे एक विजेट "ड्रा विवरणक" प्राप्त होगा।
माजिद

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

3

पुल अपने ठोस कार्यान्वयन से एक अमूर्त को हटाने का इरादा रखता है , ताकि दोनों स्वतंत्र रूप से भिन्न हो सकें:

  • उपवर्ग के साथ अमूर्त को परिष्कृत करें
  • अलग-अलग कार्यान्वयन प्रदान करें, वह भी उपवर्ग द्वारा, न तो अमूर्तता और न ही इसके शोधन के बिना।
  • यदि आवश्यक हो, तो रनटाइम चुनें जो सबसे उपयुक्त कार्यान्वयन है

रचना का उपयोग करके पुल इसे प्राप्त करता है:

  • अमूर्त एक कार्यान्वयन वस्तु को संदर्भित करता है (संदर्भ या सूचक)
  • अमूर्त और इसके शोधन को केवल कार्यान्वयन इंटरफ़ेस के रूप में जाना जाता है

यहाँ छवि विवरण दर्ज करें

एक लगातार भ्रम पर अतिरिक्त टिप्पणी

यह पैटर्न एडेप्टर पैटर्न के समान है: अमूर्त एक कार्यान्वयन के लिए एक अलग इंटरफ़ेस प्रदान करता है और ऐसा करने के लिए रचना का उपयोग करता है। परंतु:

इन पैटर्न के बीच महत्वपूर्ण अंतर उनके इरादों में निहित है
- गामा और अल, " डिजाइन पैटर्न, पुन: प्रयोज्य OO सॉफ्टवेयर का तत्व " , 1995 में

डिजाइन पैटर्न पर इस उत्कृष्ट सेमिनल बुक में, लेखक यह भी देखते हैं:

  • एक असंगति की खोज की है और युग्मन अप्रत्याशित है जब अक्सर एडेप्टर का उपयोग किया जाता है
  • पुलों का उपयोग डिजाइन की शुरुआत से किया जाता है, जब यह उम्मीद की जाती है कि कक्षाएं स्वतंत्र रूप से विकसित होंगी।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.