मुझे "ब्रिज" डिज़ाइन पैटर्न बिल्कुल भी समझ नहीं आता है। मैं विभिन्न वेब साइटों से गुजरा हूं, लेकिन उन्होंने मदद नहीं की है।
क्या कोई इसे समझने में मेरी मदद कर सकता है?
मुझे "ब्रिज" डिज़ाइन पैटर्न बिल्कुल भी समझ नहीं आता है। मैं विभिन्न वेब साइटों से गुजरा हूं, लेकिन उन्होंने मदद नहीं की है।
क्या कोई इसे समझने में मेरी मदद कर सकता है?
जवाबों:
ओओपी में हम बहुरूपता का उपयोग करते हैं इसलिए एक अमूर्त में कई कार्यान्वयन हो सकते हैं। आइए निम्नलिखित उदाहरण देखें:
//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*/}
Monorail
क्योंकि यह वास्तव में दो शब्द नहीं है, यह एक एकल (यौगिक) शब्द है। एक मोनो रेल एक अलग तरह की रेल (जो यह है) के बजाय रेल का कुछ उपवर्ग होगा। जैसे हम उपयोग नहीं करेंगे SunShine
या CupCake
, वे होंगे Sunshine
औरCupcake
जबकि अधिकांश डिज़ाइन पैटर्न में सहायक नाम होते हैं, मुझे लगता है कि "ब्रिज" नाम गैर-सहज ज्ञान युक्त है जो इसे करता है।
वैचारिक रूप से, आप एक वर्ग पदानुक्रम द्वारा उपयोग किए जाने वाले कार्यान्वयन विवरण को किसी अन्य वस्तु में, आमतौर पर अपनी पदानुक्रम के साथ धक्का देते हैं। ऐसा करने से, आप उन कार्यान्वयन विवरणों पर एक कड़ी निर्भरता को हटा रहे हैं और उस कार्यान्वयन के विवरण को बदलने की अनुमति देते हैं।
एक छोटे पैमाने पर, मैं इसे एक रणनीति पैटर्न के उपयोग के लिए पसंद करता हूं जिस तरह से आप एक नए व्यवहार में प्लग कर सकते हैं। लेकिन सिर्फ एक एल्गोरिथ्म को लपेटने के बजाय जैसा कि अक्सर एक रणनीति में देखा जाता है, कार्यान्वयन ऑब्जेक्ट आमतौर पर अधिक सुविधा से भरा होता है। और जब आप अवधारणा को पूरे वर्ग पदानुक्रम पर लागू करते हैं तो बड़ा पैटर्न एक पुल बन जाता है। (फिर से, नाम से नफरत है)।
यह एक पैटर्न नहीं है जिसे आप हर दिन उपयोग करेंगे, लेकिन मैंने इसे तब मददगार पाया है जब कक्षाओं के संभावित विस्फोट का प्रबंधन किया जा सकता है जब आपके पास कई वंशानुक्रम के लिए (स्पष्ट) आवश्यकता होती है।
यहाँ एक वास्तविक दुनिया उदाहरण है:
मेरे पास एक 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
अच्छी चीजों में से एक यह है कि मैं रन-टाइम पर कार्यान्वयन को गतिशील रूप से लोड कर सकता हूं, जिससे मुझे मुख्य सॉफ़्टवेयर को बदले बिना कई विषयों को जोड़ना होगा। दूसरे शब्दों में मेरा "कार्यान्वयन अमूर्तता से अलग हो सकता है"।
Win32TextboxPainter
और कहां Win32ListPainter
से आया Win32WidgetPainter
। आप कर सकते हैं कार्यान्वयन ओर एक विरासत पेड़ है, लेकिन यह अधिक सामान्य (शायद होना चाहिए StaticStyleControlPainter
, EditStyleControlPainter
और ButtonStyleControlPainter
आवश्यकतानुसार अधिरोहित कोई भी आवश्यक आदिम संचालन के साथ)। यह वास्तविक कोड के करीब है जो मैं उदाहरण पर आधारित था।
पुल अपने ठोस कार्यान्वयन से एक अमूर्त को हटाने का इरादा रखता है , ताकि दोनों स्वतंत्र रूप से भिन्न हो सकें:
रचना का उपयोग करके पुल इसे प्राप्त करता है:
एक लगातार भ्रम पर अतिरिक्त टिप्पणी
यह पैटर्न एडेप्टर पैटर्न के समान है: अमूर्त एक कार्यान्वयन के लिए एक अलग इंटरफ़ेस प्रदान करता है और ऐसा करने के लिए रचना का उपयोग करता है। परंतु:
इन पैटर्न के बीच महत्वपूर्ण अंतर उनके इरादों में निहित है
- गामा और अल, " डिजाइन पैटर्न, पुन: प्रयोज्य OO सॉफ्टवेयर का तत्व " , 1995 में
डिजाइन पैटर्न पर इस उत्कृष्ट सेमिनल बुक में, लेखक यह भी देखते हैं: