简体   繁体   中英

C# - Factory pattern using reflection or how?

I'm developing a game in console c#, that you can read maps created in files. For doing so, i'm reading a file and storing that into a string. Then i'm reading each character individually and depending on the character, I need to create an object using the factory pattern. I don't know how to do it without coupling the code.

I have the main entity Object. From object inherit different objects, like: Box, Wall, Grass, Tree. Each one is represented by a character in the file and translated to another character in the game, (B)ox = '■', (W)all = '▓', (G)rass = 'v', (T)ree = '↑'. The way I done that is by placing a property char "Model" in the Object with getter only, and in each object I override the getter with the corresponding model.

Now, while I'm reading the file map mentioned before I need to tell the factory which object to build depending on the character read. I dont want to make a big switch(character) because it will be coupled, because for each object I want to add I will have to add a new case in the switch. Is any better way of doing so?

Example of class Box:

public class Box : Object
{
    public override char Model { get { return '■'; } }

    public Box()
    {
        this.Name = "box";
        this.MapCharacter = 'B';
        this.Colors = new List<ConsoleColor>() { ConsoleColor.DarkYellow };
        this.Destructible = true;
        this.Passable = false;
        this.SeeThrough = false;
        this.Health = 200;
    }

    public override void OnDestroy()
    {
    }
}

Example code of Factory:

public class ObjectFactory : IObjectFactory
{
    public Object GetObject(char mapCharacter)
    {
        switch (mapCharacter)
        {
            case 'B':
                return new Box();
            case 'T':
                return new Tree();
            case 'W':
                return new Wall();
            case 'G':
                return new Grass();
            default:
                return null;
        }
    }
}

My idea was using Reflection get the Model of each class inherted from Object and somehow return that class, but that seems poor code

There are pros and cons of going with reflection (personally I would not go this way in general case) but with current code you can improve it a bit and reduce the boilerplate by "converting" switch to dictionary:

public class ObjectFactory 
{
    private static readonly Dictionary<char, Func<MyObject>> _objectFactory = new Dictionary<char, Func<MyObject>>()
    {
        { 'B', () => new Box() },
        // ...
    };

    public Object GetObject(char mapCharacter)
    {
        if(_objectFactory.TryGetValue(mapCharacter, out var factory))
        {
            return factory();
        }

        return null;
    }
}

If you will decide that adding items to dictionary every time is to much - I would recommend to look into source generators , if this approach is to much - do not forget to "cache" the reflection.

It is worth to take a look Activator.CreateInstance method.

If a map has full name of class, then it is possible to create an instance like this:

public class InstanceHelper
{
    public static object Get(string fullyQualifiedName)
    {
        Type t = Type.GetType(fullyQualifiedName);
        return Activator.CreateInstance(t);
    }
}

So the above code can be called like this:

Box box = InstanceHelper.Get("Box") as Box;

You can use this code sample . There is a class by name of EnhancedShapeFactory and it uses reflection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM