Usare un'interfaccia per creare un'astrazione

Completato

È possibile usare le astrazioni per rappresentare una funzionalità della piattaforma che viene implementata nel codice specifico della piattaforma. L'astrazione in genere comprende tutto ciò che riguarda direttamente la piattaforma o i relativi servizi. Alcuni esempi sono le notifiche, la gestione del file system o il funzionamento del thread dell'interfaccia utente.

Si supponga di usare una classe per implementare una funzionalità specifica della piattaforma che visualizza una finestra di dialogo. Il codice per una finestra di dialogo in iOS è diverso dal codice in Android. Se non si pianifica attentamente la progettazione, si rischia di creare codice duplicato. La soluzione consiste nel creare un'astrazione che descriva il comportamento della finestra di dialogo. In runtime si potrà sostituire l'astrazione con l'implementazione concreta.

In questa unità si userà un'interfaccia C# per creare un'astrazione per il codice specifico della piattaforma.

Che cos'è un'interfaccia?

Un'interfaccia è un contratto di codice che contiene definizioni per funzionalità correlate. Un'interfaccia può includere il comportamento di più origini in un'unica classe. La definizione di più comportamenti rappresenta un notevole vantaggio, perché C# non supporta l'ereditarietà di più classi.

Per definire un'interfaccia in C# si usa la parola chiave interface.

Usare un'interfaccia per creare un'astrazione

Si supponga di voler mostrare all'utente una finestra di dialogo all'interno dell'applicazione. Si vuole che la finestra abbia un titolo, un commento e un pulsante. Sfortunatamente, ogni piattaforma implementa le finestre di dialogo in modo diverso.

In iOS si userà la classe UIAlertController:

class MessageDialog_iOS
{
    public void ShowMessage(string title, string message, string buttonText)
    {
        var alert = UIAlertController.Create(title, message, UIAlertControllerStyle.Alert);

        alert.AddAction(UIAlertAction.Create (buttonText, UIAlertActionStyle.Cancel, null));
        PresentViewController(alert, animated: true, completionHandler: null);
    }
}

In Android si userà la classe AlertDialog:

class MessageDialog_Android
{
    public void ShowMessage(string title, string message, string buttonText)
    {
        new AlertDialog.Builder(this)
            .SetMessage(message)
            .SetTitle(title)
            .SetButton(buttonText, okButton_Handler)
            .Show();
    }

    private void okButton_Handler(object sender, DialogClickEventArgs e)
    {
        AlertDialog objAlertDialog = sender as AlertDialog;
        Button btnClicked = objAlertDialog.GetButton(e.Which);
        System.Diagnostics.Debug($"User clicked on the {btnClicked.Text} button");
    }
}

Si noti che i due blocchi di codice hanno elementi in comune. Ogni classe dichiara un metodo denominato ShowMessage. Inoltre, le firme di entrambe le istanze di ShowMessage sono uguali.

È ora possibile creare un'interfaccia per definire le funzionalità simili in queste due classi. Ecco un esempio:

public interface IMessageDialog
{
    void ShowMessage(string title, string message, string buttonText);
}

Si effettuerà ora il refactoring delle classi iOS e Android per implementare l'interfaccia.

L'implementazione per iOS:

class MessageDialog_iOS : IMessageDialog
{
    ...
}

L'implementazione per Android:

class MessageDialog_Android : IMessageDialog
{
    ...
}