FMPOV simply saying that Singletons are an Anti-Pattern is not correct. I agree that one should avoid globals at any case. But using singleton doesnt mean you are writing bad code or something. The problem is
the misuse of singletons, so implementing this pattern in cases where they dont fit well. Another problem is the question if a singleton would solve my current problem and doesnt end in problems later, because its really hard to foresee that. If you
are 100% sure that your singleton class only needs one valid object during runtime it is ok to use this pattern. F.e. the Engine of UE4 can be a singleton, because there are no intentions to have multiple engine objects running at the same time in one application instance.
Another example could be the GameSingleton, where you usually store persistent data and only “read” those data during runtime. As soon as you start to write in those objects it may gets complicated again.
Btw. the code:
static UDataTableHolder* DataInstance;
if(DataInstance == nullptr)
DataInstance = Cast<UDataTableHolder>(GEngine->GameSingleton);
if (!DataInstance) return NULL;
if (!DataInstance->IsValidLowLevel()) return NULL;
could be simplified and fixed with:
First, you return a Singleton object which seems to already exist in GEngine, so why storing it in another Pointer?
Second, the nullptr checks are obsolete (FMPOV), since you return NULL or nullptr indicating that this CAN RETURN NULL, a User would do these checks usually a second time after calling Get() to make sure he got a valid object. So instead i would rather place a logmessage, telling that the Object was null for some reason.
Third, the check for IsValidLowLevel is referring to GC iirc. So when instatiating Singletons you need to make sure that you have a persistent object the whole time, f.e. via Calling AddToRoot() after Ctor.
The way you describe for using this class is also something i like to do sometimes. Using it as a kind of manager or interface for a specific area you want to have access to, is also fine. And yes there are discussions about using classes called “Manager” -> this
will lead to other topics with different discussion and in the end you have the feeling that you shouldnt write any code at all
What bothers me a bit is, that you expect the GameSingleton to be a UDataTableHolder, implying that the inbuild game-wide Singleton is only used for a very small section of your game, what if you want to store other stuff than datatables in the gamesingleton?
Im looking forward to hear other opinions