Hai bisogno di un modello di progettazione per rimuovere le enumerazioni e istruzione switch in creazione di oggetti

StackOverflow https://stackoverflow.com/questions/3897221

Domanda

dire Let sto creando un gioco di sport, e in questo gioco ci sono varie posizioni che un giocatore può giocare, attacco, difesa, ecc Così comincio con la creazione di una classe di base:

public abstract class Position
{
 public abstract string Name
 {
  get;
 }
}

e sottoclassi ...

public class Defender : Position
{
 public override string Name
 {
  get { return "Defender"; }
 }
}

e così via. Questo è tutto bene.

Ma ora ho bisogno di una funzione per creare questi oggetti. Ho bisogno di un creare da funzione di posizione. Così una soluzione possibile è quella di creare un'enumerazione di tutte le posizioni e passare questo valore a una funzione che accende enum e restituisce l'oggetto appropriato. Ma questo fa scattare il mio allarme codice di odore. Questo soultion lega insieme le classi, l'enumerazione e l'interruttore all'interno di una funzione:

public static Position GetByType(Types position)
{
 switch(position)
 {
  case Types.Defender:
   return new Defender();
... and further terrible code

Quale soluzione dovrei essere guardando? Quale modello di progettazione è questo?

È stato utile?

Soluzione

Se dovete fare questo su piccola scala, l'interruttore non è davvero male, soprattutto se si vive in un unico luogo.

Se dovete fare questo su una scala media, si potrebbe prendere in considerazione migliorare l'interno un po '- il suggerimento di Steve Ellinger è ragionevole. Personalmente preferisco usare un IDictionary<MyEnum, Action<T>> dove l'azione restituisce una nuova istanza della classe in questione.

Se dovete fare questo su una scala grande o configurabile, probabilmente si dovrebbe verificare un controller IOC come StructureMap o Ninject o qualsiasi altra cosa i bambini freschi stanno giocando a questi giorni.

Altri suggerimenti

fabbrica modello .

Tuttavia può non essere un male avere un caso interruttore che accende un'enumerazione / stringa per restituire il giusto tipo di oggetto .... finché è isolato in un unico luogo .

In effetti, quello che vuoi è una fabbrica di astratto. La facilità di attuazione della fabbrica dipende dalla lingua che si sta utilizzando. php permette di nomi di classe di variabili, per esempio, in modo da poter semplicemente inviare in nome della classe e ottenere nuovi indietro $ classname. Altre lingue non consentono questo, però. Infatti, se la vostra lingua non lo fa, è già stata creata una classe di fabbrica!

non c'è davvero nulla di più elegante che si può fare a meno che non si desidera utilizzare la riflessione per simulare quello che fa php.

Un modo per affrontare con lo switch è quello di avere la fabbrica dichiarare un array di tipi e quindi utilizzare l'enumerazione come un indice nella matrice in questo modo:

public abstract class Position {
    public abstract string Name {
        get;
    }
}
public class Defender : Position {
    public override string Name {
        get { return "Defender"; }
    }
}
public class Attacker : Position {
    public override string Name {
        get { return "Attacker"; }
    }
}
public static class PositionFactory {
    public enum Types {
        Defender, Attacker
    }
    private static Type[] sTypes = new Type[] { typeof(Defender), typeof(Attacker)};
    public static Position GetByType(Types positionType) {
        return Activator.CreateInstance(sTypes[(Int32)positionType]) as Position;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top