¿Necesita un patrón de diseño para eliminar las enumeraciones y sentencia switch en la creación de objetos

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

Pregunta

Vamos a decir que estoy creando un juego de deportes, y en este juego hay varias posiciones que un jugador puede jugar, ataque, defensa, etc. Así que empezar por crear una clase base:

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

y subclases ...

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

y así sucesivamente. Todo esto está bien.

Pero ahora necesito una función para crear estos objetos. Necesito una función de posición por crear. Así que una posible solución es crear una enumeración de todas las posiciones y pasar este valor a una función que cambia en la enumeración y devuelve el objeto apropiado. Pero esto dispara la alarma de mi código de olor. Este soultion une las clases, la enumeración y el interruptor dentro de una función:

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

¿Qué solución debería estar mirando? ¿Qué patrón de diseño es esto?

¿Fue útil?

Solución

Si usted tiene que hacer esto en una escala pequeña, el cambio no es muy malo, especialmente si vive en un solo lugar.

Si usted tiene que hacer esto en una escala media, es posible que desee considerar la mejora de la parte interna un poco - la sugerencia de Steve Ellinger es razonable. En lo personal yo prefiero usar un IDictionary<MyEnum, Action<T>> donde la acción devuelve una nueva instancia de la clase en cuestión.

Si usted tiene que hacer esto en una escala Grand o configurable, probablemente debería echa un vistazo a un controlador COI, como StructureMap o ninject o lo que los chicos populares están jugando con estos días.

Otros consejos

fábrica patrón .

Sin embargo puede que no sea una mala cosa es tener una caja de conmutación, que se enciende una enumeración / cadena para devolver el tipo de objeto .... siempre y cuando es aislado en un lugar .

De hecho, lo que quiere es una fábrica de resumen. La facilidad de la aplicación de la fábrica depende del idioma que está utilizando. php permite nombres de las clases de variables, por ejemplo, por lo que sólo puede enviar en el nombre de la clase y obtener nueva vuelta $ nombre de clase. Otros idiomas no permiten esto, sin embargo. De hecho, si su idioma no hace esto, usted ha creado ya una clase de fábrica!

En realidad no hay nada más elegante que puede hacer a menos que desee utilizar la reflexión para simular lo que hace php.

Una forma de lidiar con el interruptor es tener la fábrica de declarar una matriz de tipos y luego usar la enumeración como un índice en la matriz de esta manera:

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;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top