سؤال

أحاول فهم نمط المحول واستخدامه في العالم الحقيقي. بعد الذهاب عبر مقالات مختلفة على الإنترنت و 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();
  }
}
هل كانت مفيدة؟

المحلول

بشكل عام، يحول نمط المحول واجهة واحدة إلى أخرى، ولكن يمكنه ببساطة التفاف السلوك لعزل فصولك من التنفيذ الأساسي. في حالتك، تقوم باستخدام محول، ولكن يمكنك بسهولة تحديد كائنات DAO بسهولة لنفذ الواجهة والمبرمجة ضد الواجهة. عادة ما يتم استخدام نمط المحول عندما لا يكون لديك التحكم في الفئة المستهدفة. سيكون استخدامي الأساسي لنمط المحول هو إنشاء مغلفة لفئة إطار عمل لا تنفذ واجهة.

قل أنني أريد أن أسخر من فئة إطار عمل لا تنفذ واجهة (وليس لديها طرق افتراضية). مع العديد من واجهات برمجة التطبيقات السخرية هذا من الصعب أو المستحيل القيام به. ما سأفعله، ثم، هو تحديد واجهتي مجموعة فرعية من توقيع الفصل الذي استهدفته. أقوم بتطبيق فئة مجمع تنفذ هذه الواجهة وتفويض المكالمات إلى فئة الإطار المنفوب. تعمل فئة المجمع هذه كمحول للفئة الإطارية. تستخدم فصري هذا المحول بدلا من فئة الإطار، ولكن احصل على سلوك فئة الإطار.

 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();     

نصائح أخرى

مثالا كوني داخل .NET Framework موجود في System.Drawing.Bitmap صف دراسي.

تحتوي هذه الصورة النقطية هذه على منشئ يتيح لك تحميل صورة من Stream:

public Bitmap(
    Stream stream
)

ما لا تعرفه، هو ذلك داخليا .NET Bitmap الطبقة عبارة عن مجمع حول GDI + Bitmap فئة، وبناءها الذي يأخذ IStream:

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

لذلك في العالم C #، عندما اتصلت:

new Bitmap(stream);

يجب أن يستدير والاتصال:

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

السؤال هو كيفية تقديم .NET مجرى الاعتراض على الطريقة التي تتوقع كوم iststream واجهه المستخدم.

وبالتالي الداخلية GPStream صف دراسي:

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

تحتاج إلى تقديم IStream واجهة لك Stream هدف:

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)
...                                         ...

حتى الآن لديك محول:

enter image description here

والرمز شيء مثل:

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

GdipCreateBitmapFromStream(stm, out gpBitmap);

لقد أضفت تعليقات نأمل أن تساعدك في الحصول على رأسك حول المحول / التكيف / العميل / itarget / 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 freddie = new EnglishMan(translator);

        // Freddie greets Tokyo, though he doesn't know a word of Japanese
        Console.WriteLine(freddie.Greetings()); //  "teo torriatte!"

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

        // Brian greets the crowd in Paris, though he doesn't know a word in French
        Console.WriteLine(brian.Greetings()); 
          // "So très charmant my dear! 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!!";
        }
    }
}

مثال بسيط جدا ...

 interface ITarget
    {
      List<string> GetProducts();
    }


    public class VendorAdaptee
    {
       public List<string> GetListOfProducts()
       {
          List<string> products = new List<string>();
          products.Add("Gaming Consoles");
          products.Add("Television");
          products.Add("Books");
          products.Add("Musical Instruments");
          return products;
       }
    }


    class VendorAdapter:ITarget
    {
       public List<string> GetProducts()
       {
          VendorAdaptee adaptee = new VendorAdaptee();
          return adaptee.GetListOfProducts();
       }
    }


    class ShoppingPortalClient
    {
       static void Main(string[] args)
       {
          ITarget adapter = new  VendorAdapter();
          foreach (string product in adapter.GetProducts())
          {
            Console.WriteLine(product);
          }
          Console.ReadLine();
       }
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top