2010-10-09 9 views
1

Disons que je crée un jeu de sport, et dans ce jeu il y a différentes positions qu'un joueur peut jouer, attaquer, défendre, etc. Donc je commence par créer une classe de base:Besoin d'un motif de design pour supprimer les enums et changer de déclaration dans la création d'objet

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

et les sous-classes ...

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

et ainsi de suite. Tout va bien.

Mais maintenant j'ai besoin d'une fonction pour créer ces objets. J'ai besoin d'une fonction de création par position. Une solution possible est donc de créer une énumération de toutes les positions et de passer cette valeur à une fonction qui active l'énumération et renvoie l'objet approprié. Mais cela déclenche mon alarme de code. Cette soultion relie les classes, l'ENUM et l'interrupteur dans une fonction:

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

Quelle solution dois-je envisager? Quel est le motif de conception?

Répondre

4

Si vous devez le faire sur une à petite échelle, l'interrupteur n'est pas vraiment mauvais, surtout s'il vit à un endroit unique.

Si vous devez le faire à une échelle moyenne, vous pourriez envisager d'améliorer un peu les internes - la suggestion de Steve Ellinger est raisonnable. Personnellement, je préfère utiliser un IDictionary<MyEnum, Action<T>> où l'action renvoie une nouvelle instance de la classe en question. Si vous devez le faire sur une échelle grand ou configurable, vous devriez probablement vérifier un contrôleur IoC tel que structuremap ou ninject ou quoi que les enfants cool jouent avec ces jours-ci.

+0

Pour l'instant j'utilise un dictionnaire. Dans le futur je voudrais que cette étape soit configurable donc cette réponse va m'aider le plus, merci! – DanDan

3

On dirait le Factory pattern.

Cependant, il ne peut pas être une mauvaise chose d'avoir un boîtier de commutation, qui active une énumération/chaîne pour retourner le bon type d'objet .... tant qu'il est isolé en un seul endroit.

1

En effet, ce que vous voulez est une usine abstraite. La facilité de mise en œuvre de l'usine dépend de la langue que vous utilisez. php permet par exemple des noms de classes variables, donc vous pouvez juste envoyer le nom de la classe et récupérer le nouveau $ classname. Cependant, d'autres langues ne le permettent pas. En fait, si votre langue ne le fait pas, vous avez déjà créé une classe d'usine!

Il n'y a pas vraiment quelque chose de plus élégant que vous pouvez faire, sauf si vous voulez utiliser la réflexion pour simuler ce que php fait.

1

Une façon de traiter avec le commutateur est d'avoir l'usine déclarer un tableau de types puis utilisez l'énumération comme un index dans le tableau comme ceci:

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; 
    } 
} 
+0

Merci pour le code! Très intéressant. – DanDan