Lavorare con il modello di progettazione dell'adattatore

I modelli di progettazione sono soluzioni a problemi ricorrenti e complessità nella progettazione del software. I modelli di progettazione sono classificati come creazionali, strutturali o comportamentali. I modelli di creazione vengono utilizzati per creare e gestire il meccanismo di creazione di istanze di classi. I modelli strutturali vengono utilizzati per realizzare le relazioni tra le entità. I modelli di progettazione comportamentale si occupano della collaborazione degli oggetti e della delega delle responsabilità.

Il pattern Adapter è un pattern di progettazione strutturale che funge da ponte tra due interfacce incompatibili. Il termine "Adattatore" viene utilizzato per rappresentare un oggetto che consente a due interfacce reciprocamente incompatibili di comunicare e collaborare. In sostanza, il pattern Adapter consente alle classi (che hanno interfacce incompatibili) di lavorare insieme e i loro oggetti comunicano se necessario.

Esistono alcuni tipi di adattatori che implementano le interfacce di Target e Adaptee. Tali tipi di adattatori sono noti come adattatori a due vie. Hai anche due tipi distinti di adattatori, ovvero adattatori di classe e adattatori di oggetti. Mentre il primo utilizza l'ereditarietà, il secondo utilizza la composizione per risolvere i problemi di incompatibilità nei tuoi progetti. È possibile utilizzare il modello di progettazione dell'adattatore quando è necessario utilizzare una libreria di terze parti che non è compatibile con i tipi presenti nell'applicazione.

Di seguito è riportato l'elenco dei tipi che partecipano a un'implementazione tipica del pattern Adapter:

  • Bersaglio
  • Adattatore
  • Adaptee
  • Cliente

Capiamolo con un esempio. Supponiamo che due persone che parlano e comprendono lingue diverse debbano comunicare: una potrebbe essere il francese e l'altra il tedesco. Quindi, queste due persone possono parlare e capire rispettivamente solo il francese e il tedesco, non entrambi. Normalmente avresti bisogno di qualcuno (un interprete) che conosca entrambe queste lingue per facilitare la comunicazione. Quindi, la persona che può facilitare questa comunicazione funge da adattatore.

Questo modello rientra nella categoria strutturale poiché utilizzeresti questo modello per strutturare i tipi nella nostra applicazione - in genere questo modello può trasformare un'interfaccia in un'altra. La Gang of Four definisce il pattern Adapter come "Converti l'interfaccia di una classe in un'altra interfaccia che i client si aspettano. Adapter consente alle classi di lavorare insieme che altrimenti non potrebbero a causa di interfacce incompatibili".

Analizziamo ora un po 'di codice. Considera le seguenti due classi.

public class TargetA

            {

                public void DisplayA()

                {

                    Console.WriteLine("TargetA");

                }

            }

            public class TargetB

            {

                public void DisplayB()

                {

                    Console.WriteLine("TargetB");

                }

            }

Come puoi vedere, le due classi sono incompatibili - non hanno nemmeno una base comune. L'elenco di codice seguente mostra l'aspetto delle classi dell'adattatore.

public interface ITargetAdapter

            {

                void ProcessData();

            }

public class AdapterA : ITargetAdapter

            {

                 public TargetA targetA { get; set; }

                 public void Process()

                 {

                     targetA.DisplayA();

                 }

                 public AdapterA(TargetA obj)

                 {

                     targetA = obj;

                 }

            }

            public class AdapterB : ITargetAdapter

            {

                 public TargetB targetB { get; set; }

                 public void Process() { targetB.DisplayB(); }

                 public AdapterB(TargetB obj)

                 {

                     targetB = obj;

                 }

            }

Notare che entrambe le classi dell'adattatore hanno un'interfaccia comune denominata ITargetAdapter che queste classi implementano. Ciascuna delle due classi dell'adattatore ha un costruttore di argomenti che accetta un riferimento a un oggetto delle rispettive classi di destinazione. L'interfaccia ITargetAdapter contiene la dichiarazione del metodo Process (). Questo metodo è implementato da entrambe le classi dell'adattatore: questi metodi richiamano Display () ei rispettivi metodi di visualizzazione delle classi di destinazione che abbiamo implementato in precedenza.

Il seguente listato di codice illustra come utilizzare queste classi di adattatori.

class Program

    {

        static void Main(string[] args)

        {

            ITargetAdapter adapter = new AdapterA(new TargetA());

            adapter.Process();

            adapter = new AdapterB(new TargetB());

            adapter.Process();

            Console.Read();

        }

Come puoi vedere nello snippet di codice sopra, dobbiamo passare un'istanza della rispettiva classe di destinazione al costruttore della classe dell'adattatore.

Presenterò le discussioni su più modelli di progettazione nei miei prossimi post qui. Il modello di progettazione dell'adattatore può essere una buona scelta quando è necessario richiamare il codice legacy nelle applicazioni. Puoi saperne di più sul modello di progettazione dell'adattatore da questo articolo.