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.