Classe base astratta che implementa un'interfaccia, fornendo una classe diversa alle sue sottoclassi

1

Diciamo che ho un'interfaccia per il pattern Command con funzionalità di annullamento:

interface ICommand
{
    void Execute();
    void Undo();
}

Questo è accompagnato da un contratto. Fondamentalmente il comando può essere in uno dei due stati - o è stato eseguito o meno, e questo determina l'unico metodo che può essere chiamato.

Per aggiungere un controllo per questo, potrei creare una classe astratta chiamata SafeCommand o semplicemente CommandBase con questa protezione:

abstract class CommandBase : ICommand
{
    private bool executed = false;

    public void Execute()
    {
        if (executed)
            throw new InvalidOperationException();

        ExecuteImpl();
        executed = true;
    }

    public void Undo()
    {
        if (!executed)
            throw new InvalidOperationException();

        UndoImpl();
        executed = false;
    }

    protected abstract void ExecuteImpl();
    protected abstract void UndoImpl();
}

Quando voglio implementare l'effettiva funzionalità di comando, ora devo sostituire i metodi ExecuteImpl e UndoImpl.

Un altro modo per risolvere questo potrebbe essere quello di rendere i metodi virtuali, ma preferisco in questo modo perché non posso dimenticare di implementare i metodi e inoltre non posso omettere la chiamata di base. Inoltre, negli altri casi in cui ho bisogno di avere del codice prima e dopo la chiamata, questa sarà l'unica soluzione.

Ho incontrato questo pattern per la prima volta in WPF, dove è effettivamente usato due volte nella stessa gerarchia di ereditarietà con UIElement Measure, MeasureCore virtuale e FrameworkElement sovrascrivono i metodi MeasureCore e MeasureOverride virtuali.

La mia domanda è, c'è un nome per questo modello? Mi sembra una sorta di adattatore (forzato) che utilizza l'ereditarietà invece della composizione.

    
posta Neme 29.12.2017 - 12:48
fonte

1 risposta

0

L'unico vero pattern GOF che posso vedere in questo costrutto è il "modello di metodo del modello" .

L'interfaccia pubblica di qualsiasi derivazione di CommandBase - vista da qualsiasi codice al di fuori della gerarchia di classi - non cambia, quindi non la vedo come

"providing a different interface to the subclasses",

come impone il titolo della tua domanda. La mia interpretazione di questo è più "che fornisce un modo più semplice per implementare l'interfaccia con il controllo degli errori" .

La domanda più interessante qui è: c'è una violazione LSP? Penso di no, se il contratto è scritto esattamente come indicato nella domanda, con l'osservazione aggiuntiva che Execute e Undo generano eccezioni quando vengono chiamate nell'ordine sbagliato. Quindi il modello di metodo del modello aiuterà effettivamente a garantire il contratto.

    
risposta data 29.12.2017 - 13:23
fonte

Leggi altre domande sui tag