Abilita l'accesso agli oggetti tramite Introduce oggetto parametro o interfaccia

-1

Sto lavorando con più comandi che vengono eseguiti in ordine (e possibilmente anche con comandi secondari) che possono essere descritti come segue:

interface ICommand
{
    void Execute();
}

abstract class AbstractCommand : ICommand
{
    protected List<ICommand> ChildCommands { get; }

    public virtual void Execute()
    {
        foreach (var childCommand in ChildCommands)
            childCommand.Execute(arguments);
    }
}

class SampleCommand : AbstractCommand
{
    public override void Execute()
    {
        base.Execute();
    }
}

Questi comandi sono eseguiti da un'altra classe che li memorizza:

class Generator
{
    private Grid[,] Layout { get; }
    private List<ICommand> Commands { get; }

    public void RunCommands()
    {
        foreach (var command in Commands)
            command.Execute();
    }
}

L'intenzione è che i comandi possano liberamente manipolare la matrice Layout e possibilmente alcuni altri oggetti che introdurrò in una fase successiva. Questo mi richiederebbe di passarli per riferimento ma ho notato che già con 10+ comandi il refactoring diventerà insopportabile una volta che deciderò di esporre un altro oggetto da Generator a tutti ICommand s. Pertanto ho preso in considerazione l'introduzione di una classe CommandArguments che ha memorizzato il Layout per riferimento e possibilmente di più e ha modificato la firma di Execute() in Execute(CommandArguments) .

Purtroppo non mi piace pensare di manipolare gli argomenti con ref e considerare di introdurre un'interfaccia IGenerator per accedere agli oggetti tramite metodi e cambiare la firma in Execute(IGenerator) come questa:

interface IGenerator
{
    void DoSomething();
}

class SampleCommand : AbstractCommand
{
    public override void Execute(IGenerator gen)
    {
        gen.DoSomething();
        base.Execute(gen);
    }
}

class Generator : IGenerator
{
    private Grid[,] Layout { get; }
    private List<ICommand> Commands { get; }

    public void RunCommands()
    {
        foreach (var command in Commands)
            command.Execute(this);
    }

    public void DoSomething()
    {
        /* do something with Layout here */
    }
}

Mi piacerebbe sapere se l'utilizzo di questa interfaccia è migliore rispetto all'utilizzo della classe CommandArguments e se c'è qualcos'altro che posso migliorare.

Modifica

Da quando sono stato chiesto ulteriori spiegazioni ecco maggiori informazioni: il codice è usato in un generatore per i livelli generati proceduralmente. I dati necessari sono memorizzati nella classe Generator mentre la generazione è descritta da varie regole come AddRoom , AddHub , AddEvent a cui si fa riferimento come comandi. Tuttavia, sto considerando di implementare più generatori che si comportano in modo leggermente diverso (ad esempio, i livelli interno ed esterno hanno generatori diversi) mentre i generatori possono esporre determinati metodi che hanno in comune con le regole / comandi al fine di impedire sia l'accesso diretto agli oggetti sottostanti sia assicurandoti di gestirli correttamente.

    
posta Christian Ivicevic 23.09.2017 - 15:27
fonte

1 risposta

0

Ho un'idea del tipo di applicazione che stai scrivendo. Se si tratta di un tipo di editor grafico, gli argomenti del comando devono essere proprietà (o campi) immutabili contenute negli argomenti del comando. Se sono necessari alcuni dati globali, per essere manipolati, dovrebbe essere passato al metodo di esecuzione del comando in alcuni oggetti contenitore. Sfortunatamente è difficile creare oggetti di stato (stato dell'editor) che sono molto specifici di un comando quando si fa questo tipo di lavoro. Il meglio che puoi fare è avere un oggetto di alto livello che contenga oggetti secondari specifici per un'area di funzionalità.

    
risposta data 24.09.2017 - 19:28
fonte

Leggi altre domande sui tag