2009-08-19 8 views
21

मैं एडाप्टर पैटर्न और वास्तविक दुनिया में इसका उपयोग समझने की कोशिश कर रहा हूं। इंटरनेट और www.dofactory.com पर विभिन्न लेखों के माध्यम से जाने के बाद, मैंने यह नमूना कोड बनाया। मैं सिर्फ यह जानना चाहता हूं कि मेरी समझ सही है या नहीं। नीचे दिए गए उदाहरण में मैंने एडाप्टर क्लास में MSDAO ऑब्जेक्ट बनाया है। बाद में मैंने इसे ओरेकलडाओ में बदल दिया।एडाप्टर पैटर्न को समझना

class Client 
{ 
    static void Main(string[] args) 
    { 
    ITarget objAdapter = new Adapter(); 
    object dummyObject = objAdapter.GetData(); 
    } 
} 

Interface ITarget 
{ 
    public void GetData(); 
} 

//Decision to use MSDAO 

class Adapter : ITarget 
{ 
    public void GetData() 
    { 
    MSDAO objmsdao = new MSDAO(); 
    objmsdao.GetData(); 
    } 
} 

//After a month, the decision to use OracaleDAO was taken, so the code change 

class Adapter : ITarget 
{ 
    public void GetData() 
    { 
    OracleDAO objoracledao = new OracleDAO(); 
    objoracledao.GetData(); 
    } 
} 

उत्तर

61

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

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

public interface IFoo 
{ 
    void Bar(); 
} 

public class FooWrapper : IFoo 
{ 
     private FrameworkFoo Foo { get; set; } 

     public FooWrapper(FrameworkFoo foo) 
     { 
      this.Foo = foo; 
     } 

     public void Bar() 
     { 
      this.Foo.Bar(); 
     } 
} 

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

फ्रेमवर्क कक्षाएं:

public class TargetA 
{ 
    public void Start() { ... } 
    public void End() { ... } 
} 

public class TargetB 
{ 
    public void Begin() { ... } 
    public void Terminate() { ... } 
} 

उन्हें

public interface ITargetAdapter 
{ 
    void Open(); 
    void Close(); 
} 

public class AdapterA : ITargetAdapter 
{ 
    private TargetA A { get; set; } 

    public AdapterA(TargetA a) 
    { 
      this.A = a; 
    } 

    public void Open() { this.A.Start(); } 
    public void Close() { this.A.End(); } 
} 

public class AdapterB : ITargetAdapter 
{ 
    private TargetB B { get; set; } 

    public AdapterB(TargetB a) 
    { 
      this.B = a; 
    } 

    public void Open() { this.B.Begin(); } 
    public void Close() { this.B.Terminate(); } 
} 

के लिए एक अनुकूलक तब के रूप में इस्तेमाल:

ITargetAdapter adapter = new AdapterA(new TargetA()); 
adapter.Open(); 
adapter.Close();  
+0

आपके उदाहरण में, आपने अपनी फ्रेमवर्क क्लास को एक कक्षा के साथ लपेट लिया है जो इंटरफ़ेस लागू करता है। मैंने इसे समझा है, लेकिन क्या आप यह स्पष्ट कर सकते हैं कि आपने "एक इंटरफ़ेस को दूसरे में कैसे बदल दिया है? धन्यवाद। – pradeeptp

+0

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

+0

धन्यवाद। यह अब बहुत स्पष्ट है! – pradeeptp

2

एक विहित उदाहरण के अंदर .NET फ़्रेमवर्क System.Drawing.Bitmap वर्ग में मौजूद है।

यह बिटमैप एक निर्माता आप एक Stream से एक छवि को लोड करने देता है कि दिया गया है:,

public Bitmap(
    Stream stream 
) 

आप नहीं जानते कि क्या है कि आंतरिक रूप से नेट Bitmap वर्ग GDI + Bitmap वर्ग के चारों ओर एक आवरण है, सी # दुनिया में

Bitmap(
    [in] IStream *stream, 
    [in] BOOL useIcm 
); 

तो, जब मैं फोन: और इसके निर्माता लेता है कि एक IStream

new Bitmap(stream); 

यह बिलकुल पलट गया और कॉल करने के लिए है:

IStream stm; 
IntPtr gpBitmap; 
GdipCreateBitmapFromStream(stm, out gpBitmap); 

सवाल यह है कि एक पेश करने के लिए है।नेट स्ट्रीम एक ऐसी विधि पर ऑब्जेक्ट जो COM ISTream इंटरफ़ेस की अपेक्षा करता है।

इसलिए आंतरिक GPStream वर्ग:

internal class GPStream : IStream 
{ 
    GPStream(Stream stream) { ... } 
} 

आप अपने Stream वस्तु के लिए एक IStream इंटरफेस पेश करने के लिए की जरूरत है:

enter image description here

:

IStream          Stream 
=======================================  ===================================== 
int Read(IntPtr buf, int len);   --> int Read(byte[] buffer, int offset, int count) 
int Write(IntPtr buf, int len);   --> void Write(byte[] buffer, int offset, int count); 
long Seek(long dlibMove, int dwOrigin); --> long Seek(long offset, SeekOrigin orgin) 
...           ... 

तो अब आप एक एडाप्टर है

और कोड है कुछ की तरह:

IStream stm = new GPStream(stream); //adapter to convert Stream --> IStream 
IntPtr gpBitmap; 

GdipCreateBitmapFromStream(stm, out gpBitmap); 
0

मैं टिप्पणियों जो उम्मीद है कि मदद से आप अपने पूरे अनुकूलक/adaptee/ग्राहक/Itarget शब्दजाल के आसपास सुना पाने जोड़ दिया है - जो एक छोटे से भ्रामक है - एक उदाहरण के साथ कि उम्मीद है कि अधिक सहज हो - उम्मीद है :) :) (उंगलियों को पार किया)।

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     // Brian and freddie know only how to say Greetings. But when they tour 
     // internationally, they will need a translator so when they say Greetings() 
     // the appropriate non-English response comes out of their mouth. 
     // they need to make use of the adapter pattern: 

     // When in Japan: 
     ITarget translator = new JapaneseTranslator(new JapaneseSpeaker()); 
     EnglishMan freddieMercury = new EnglishMan(translator); 

     // Freddie greets the Tokyo crowd, though he doesn't know a word of Japanese 
     Console.WriteLine(freddieMercury.Greetings()); // "Konichiwa, hisashiburi!" 

     // when in France: 
     ITarget translator2 = new FrenchTranslator(new FrenchSpeaker()); 
     EnglishMan brianMay = new EnglishMan(translator2); 

     // Brian greets the crowd in Paris, though he doesn't know a word in French 
     Console.WriteLine(brianMay.Greetings()); // "Bonjour!" 

     // alternatively, the translators can also do the greeting: 
     Console.WriteLine(translator.Greetings()); // "Konichiwa, hisashiburi!" 
     Console.WriteLine(translator2.Greetings()); // "Bonjour!" 
    } 

    /// <summary> 
    /// This is the client. 
    /// </summary> 
    public class EnglishMan : ITarget 
    { 
     private ITarget target; 

     public EnglishMan(ITarget target) 
     { 
      this.target = target; 
     } 

     public string Greetings() 
     { 
      return target.Greetings(); 
     } 
    } 

    /// <summary> 
    /// The target interface 
    /// </summary> 
    public interface ITarget 
    { 
     string Greetings(); 
    } 

    /// <summary> 
    /// This is the adaptor 
    /// </summary> 
    public class JapaneseTranslator : ITarget 
    { 
     private JapaneseSpeaker japanese; 

     public JapaneseTranslator(JapaneseSpeaker japanese) 
     { 
      this.japanese = japanese; 
     } 

     public string Greetings() 
     { 
      return japanese.Konnichiwa(); 
     } 
    } 

    /// <summary> 
    /// This is the adaptee 
    /// </summary> 
    public class JapaneseSpeaker 
    { 
     public JapaneseSpeaker() 
     { 
     } 

     public string Konnichiwa() 
     { 
      return "Konichiwa, hisashiburi!"; 
     } 
    } 

    /// <summary> 
    /// This is the adaptor 
    /// </summary> 
    public class FrenchTranslator : ITarget 
    { 
     private FrenchSpeaker french; 

     public FrenchTranslator(FrenchSpeaker french) 
     { 
      this.french = french; 
     } 

     public string Greetings() 
     { 
      return french.Bonjour(); 
     } 
    } 

    /// <summary> 
    /// This is the adaptee 
    /// </summary> 
    public class FrenchSpeaker 
    { 
     public string Bonjour() 
     { 
      return "Bonjour!!"; 
     } 
    } 
}