Search code examples
c#unity-game-enginegenericsinterfacefactory

Generics and Factory pattern


I'm trying to implement a base factory class that has a list of different instances with different IDs in Unity. It will have a list of prefabs I mean.

I'm going to implement lots of different factories for my game and they all will have different list of prefabs.

I've created a common interface for creatable (instantiatable) objects. When I give an Id to the factory, it will find the prefab that has the Id on it and will return instantiated item.

But i need some help because I felt like I'm doing something wrong or there is a way better.

I've created an interface named ICreatable and a BaseFactory. Here is what I did so far;

This is the interface;

    public interface ICreatable<T> where T : MonoBehaviour
    {
        #region Properties

        public int Id { get; }
        public T Item { get; }

        #endregion Properties
    }

And this is the base factory;

    public class BaseFactory<T, U> where T : MonoBehaviour where U : ICreatable<T>
    {
        #region Variables

        protected T cachedItem;
        protected U cachedCreatable;

        protected List<U> creatableList;

        #endregion Variables

        #region Functions

        public BaseFactory(List<U> creatableList)
        {
            this.creatableList = new List<U>(creatableList);
        }

        ~BaseFactory()
        {
            creatableList = null;
        }

        public T Manufacture(int id)
        {
            cachedCreatable = GetCreatable(id);
            cachedItem = UnityEngine.Object.Instantiate(cachedCreatable.Item, null);

            return cachedItem;
        }

        private U GetCreatable(int id)
        {
            for (int i = 0; i < creatableList.Count; i++)
            {
                cachedCreatable = creatableList[i];

                if (cachedCreatable != null && cachedCreatable.Id == id)
                {
                    return cachedCreatable;
                }
            }

            return default;
        }

        #endregion Functions
    }

And then I needed to create an ammo factory for example;

    public class AmmoFactory : BaseFactory<BaseAmmo, BaseAmmo> { }

This is the point where I felt like I'm doing something wrong. Because I need to give BaseAmmo twice. I cannot make sth like public class BaseFactory<ICreatable<T>> for sure but I need some advices or a good lesson.

Thank you so much in advance.


Solution

  • A suggestion was made in a comment and was warmly received by the OP.

    The suggestion is to not to have two distinct generic parameters but just one and follow a commonly used pattern where a type implements an interface on its own:

    public class BaseFactory<T> 
       where T : MonoBehaviour, ICreatable<T>