Base Class vs Common Member Class

2

Immagina di avere due classi come questa ...

public class SingleplayerGameSetup
{
    public int Seed { get; private set; }
    public int AiNations { get; private set; }
}

public class MultiplayerGameSetup
{
    public int Seed { get; private set; }
    public int AiNations { get; private set; }
    public List<IpAdress> Clients { get; private set; }
}

... e davvero non mi piace il fatto che abbiano membri comuni.

Quando prendo l'approccio della classe base, la classe SingleplayerGameSetup diventa vuota:

public abstract class GameSetup
{
    public int Seed { get; private set; }
    public int AiNations { get; private set; }
}

public class SingleplayerGameSetup : GameSetup
{
    //This class is basically empty right now.
}

public class MultiplayerGameSetup : GameSetup
{
    public List<IpAdress> Clients { get; private set; }
}

L'altro modo in cui posso pensare è creare una classe che contenga i membri comuni:

public class SharedGameSetupSettings
{
    public int Seed { get; private set; }
    public int AiNations { get; private set; }
}

public class SingleplayerGameSetup
{
    public SharedSettings SharedGameSetupSettings { get; set; }
}

public class MultiplayerGameSetup
{
    public SharedSettings SharedGameSetupSettings { get; set; }
    public List<IpAdress> Clients { get; private set; }
}

Quale approccio è migliore? O c'è un approccio migliore?
Grazie.

    
posta S. Tarık Çetin 26.07.2016 - 01:13
fonte

3 risposte

2

Chiamiamo la prima opzione opzione A e la seconda opzione B.

Il tuo unico dubbio sull'opzione A è che SingleplayerGameSetup "è praticamente vuoto in questo momento." .

Penso che non abbia importanza perché ovviamente il tuo codice crescerà con il tempo e le probabilità sono SingleplayerGameSetup non sarà vuoto per sempre. Non puoi prevedere il futuro.

Nell'opzione B, dovresti scrivere metodi di wrapping per ogni SharedGameSetupSettings (che sarà una lista piuttosto lunga di impostazioni che sto supponendo), o accedere alle impostazioni condivise in un modo e alle impostazioni non condivise in un altro modo.

Penso che per il punto di vista del codice client tutte le impostazioni dovrebbero essere accessibili allo stesso modo.

Anche se di solito sono propenso a favorire la composizione piuttosto che l'ereditarietà, in questo caso andrei con l'opzione A.

    
risposta data 26.07.2016 - 14:16
fonte
2

La seconda opzione ha più senso da un punto di vista dell'incapsulamento e della responsabilità di classe. In effetti, la parola "Condivisa" non è realmente richiesta: le impostazioni catturano un seme e un'informazione (qualunque esse siano) per qualsiasi configurazione di gioco.

Non raccomanderei di creare classi astratte solo per abilitare il riutilizzo del codice, a meno che la classe / interfaccia astratta non definisca realmente la firma di ciò che rappresenta e di tutte le implementazioni. Infatti nell'esempio sopra, oltre all'introduzione della classe Settings, si potrebbe anche definire un'interfaccia che definisca la firma che tutte le implementazioni di GameSetup necessitano di un modo per definire le Impostazioni - cioè una nuova interfaccia chiamata GameSetup che ha un metodo getSettings () , che implementano sia SinglePlayerGameSetup che MultiPlayerGameSetup - perché immagino che tu non possa avere un GameSetup senza definire impostazioni per esso.

    
risposta data 26.07.2016 - 01:36
fonte
1

Non c'è davvero differenza da ciò che hai ora e dalla seconda opzione che hai affermato. Ancora una volta, hai membri comuni, solo che ora sono incapsulati in una classe. Questo mitiga il problema quando devi aggiungere o modificare qualcosa in SharedGameSetupSettings, ma se devi aggiungere qualcos'altro che è comune sia per SingleplayerGameSetup che per MultiplayerGameSetup e non è correlato a SharedGameSetupSettings, hai lo stesso problema di prima.

Pertanto, ti rimane la prima opzione. L'alternativa può essere quella di non rendere SinglePlayerGameSetup una classe astratta. Se questo è l'intero ambito del tuo problema, a mio avviso questo approccio è il migliore. Hai tutto ciò che ti serve lì e la tua soluzione non è sovradimensionata.

Tuttavia, come ha detto @Tulains Córdova, è altamente improbabile che queste classi non crescano, il che rende il primo progetto una scelta logica.

    
risposta data 26.07.2016 - 14:35
fonte

Leggi altre domande sui tag