Come faccio a fornire un "modello" per una classe quando non posso usare una classe base e non ho bisogno di un'interfaccia?

-1

Ho un paio di classi derivate che sono generalmente simili, ma non hanno una classe base direttamente condivisa. Tutte queste classi implementano un'interfaccia comune. Ho notato quando ho aggiunto un'altra (nuova) classe derivata, che copio un paio di metodi privati dalle altre classi che hanno contenuti simili, ma l'implementazione effettiva differisce un po '. Hanno principalmente a che fare con il funzionamento interno della classe e non devono essere pubblici o interni.

Esempio:

public class MyButton : Button, ICoolFoo
{
    private void InitializeFoo()
    {
        // Only used from class
    }

    private void UpdateFoo()
    {
        // Only used from class
    }

    public Foo SomeFoo()
    {
        // From ICoolFoo.
    }
}

public class MyLabel : Label, ICoolFoo
{
    private void InitializeFoo()
    {
        // Only used from class
    }

    private void UpdateFoo()
    {
        // Only used from class
    }

    public Foo SomeFoo()
    {
        // From ICoolFoo.
    }
}

I metodi di inizializzazione e aggiornamento vengono utilizzati solo dall'interno della classe e non richiedono l'accesso dall'esterno. Il consumatore di queste classi non si preoccupa di loro quindi inserirle in un'interfaccia lo farebbe gonfiare inutilmente.

Ora, dal punto di vista dello sviluppatore, devo documentare che gli implementatori di ICoolFoo dovrebbero avere una struttura simile per mantenere i dettagli simili e facili da seguire, ma sono irrilevanti all'esterno. Idealmente aggiungerei qualcosa come una classe base con membri virtuali privati che posso aggiungere a qualsiasi nuova classe con poche sequenze di tasti, ma ovviamente non funziona.

Esistono modelli o un'architettura intelligente per migliorare questo design?

    
posta Lennart 28.08.2017 - 13:39
fonte

2 risposte

2

Supponendo che non sia possibile modificare Button e / o Label , non c'è molto margine per quanto riguarda la derivazione, poiché C # ha solo ereditarietà singola.

Quindi, dovresti passare alla composizione, probabilmente nella forma del schema del proxy . Il pattern proxy consente effettivamente l'avvio di una nuova catena di ereditarietà.

Non ci sono abbastanza dettagli nella domanda per raccomandare un modello specifico. Tuttavia, le opzioni che utilizzano un pattern proxy includono:

  • usa una nuova classe base astratta CoolFoo che implementa ICoolFoo , che è sottoclassata da MyButton (come in class MyButton : CoolFoo ) e opera come proxy per Button .

  • usa una classe generica class CoolFoo<T> : ICoolFoo , dove T sarà passato Button o Label . Ciò consentirà l'acquisizione dell'oggetto che viene delegato all'interno della classe generica e le implementazioni del metodo in questa classe generica possono fare riferimento a tale stato (in modo che possano essere più complete e magari condivise).

  • una combinazione di quanto sopra, ad es. sottoclasse la classe generica per rendere MyButton , come in class MyButton: CoolFoo<Button> { ... }

Se necessario, puoi anche creare una sottoclasse del Button originale (senza implementare l'interfaccia) nel caso in cui sia necessaria la specializzazione Button oltre all'interfaccia.

Dal punto di vista del design, penso che uno di questi potrebbe essere più pulito. Sembra che potresti avere troppe cose in corso in una singola classe (specialmente per C #), data la sottoclasse e anche l'implementazione dell'interfaccia.

Essenzialmente i suggerimenti sopra riportati separano ulteriormente le tue classi base esistenti, dall'implementazione dell'interfaccia.

    
risposta data 28.08.2017 - 18:00
fonte
2

Mi sembra che questo problema non richieda una soluzione nel modello a oggetti. Dopo tutto non ci sono dipendenze da questi metodi e non garantiscono un'interfaccia. Quindi inquinare la tua eredità e le altre relazioni oggettuali solo per quello sembra inappropriato, specialmente se ci sono mai eccezioni. Vuoi solo che i tuoi sviluppatori seguano uno schema.

Un modo per farlo è impostarli con un modello di classe. Puoi certamente scrivere i tuoi modelli in modo che quando scelgono "Aggiungi nuovo elemento" verrà visualizzato. Vedi Come faccio a modificare i modelli di Visual Studio? .

Un'altra cosa che potresti considerare è la creazione di un FxCop o StyleCop regola che controlla questo pattern e fallisce la build se non viene rispettata.

    
risposta data 29.08.2017 - 01:20
fonte

Leggi altre domande sui tag