Need a design pattern to remove enumerations and a switch statement when creating an object

Let's say I create a sports game, and in this game there are various positions that the player can play, attack, defend, etc. Therefore, I start by creating a base class:

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

and subclasses ...

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

etc. Everything is good.

But now I need a function to create these objects. I need a create by position function. Thus, one of the possible solutions is to create an enumeration of all positions and transfer this value to a function that includes the enumeration and returns the corresponding object. But this is alarming from my code smell. This soul binds classes, listing, and switch inside a function:

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

What solution should I look for? What design pattern is this?

+1
source share
4 answers

If you need to do this on a small scale, the switch is not very bad, especially if it lives in one place.

If you need to do this on an average scale, you may need to improve the interior design a bit - Steve Ellinger's suggestion is reasonable. Personally, I prefer to use IDictionary<MyEnum, Action<T>> , where Action returns a new instance of the class in question.

If you need to do this on a large or custom scale, you should probably check out an IoC controller like mapmap or ninject or whatever cool kids play with these days.

+4
source

Sounds like a Factory pattern .

However, it may not be so bad to have a switch case that includes an enum / string to return the correct type of object .... as long as it is isolated in one place .

+3
source

In fact, you need an abstract factory. The simplicity of the factory implementation depends on the language you use. For example, php allows class variable names, so you can just send the class name and get the new $ classname. However, other languages ​​do not allow this. In fact, if your language does not, you have already created the factory class!

Actually there is nothing more elegant if you do not want to use reflection to imitate what php does.

+1
source

One way to solve this problem is to factory declare an array of types, and then use the enumeration as an index in the array, for example:

 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; } } 
+1
source

Source: https://habr.com/ru/post/1444862/


All Articles