Dein Konzept spricht jetzt aber nicht direkt gegen Singletons. Du schreibst die Klassen sollen testbar sein. Ein Singleton kann man natürlich auch testen. Es verändert ein Objekt ja jetzt nicht so, dass es nicht mehr testbar ist. Da verstehe ich den Zusammenhang nicht ganz. Und auch für den Editor. Wenn das ganze über ein Singleton implementiert wäre, könnte man es dennoch austauschen. Das Singleton sagt ja erst mal nur, dass das Objekt nur ein mal da ist. Es sagt aber nicht, dass ein Singleton kein Interface implementieren kann, welches auch von einer anderen Klasse implementiert wird. Du kannst ein Singleton global beziehen, musst dies aber nicht tun. Von daher ist das eher wieder ein Punkt der gegen globale Variablen spricht, was hier ja am Ende mit reinkommt.
Naja ein Singleton ist nur bedingt testbar, da es über mehrere Tests seinen internen State behält, genau das ist ja der Sinn - nur genau eine Instanz. Wenn man nun Test-Mapdaten in so etwas läd, müsste man immer eine Art Reset- / Clear-Methode bauen um ihn sauber neu zu initialisieren. Wir verwenden in unseren Gameservern (leider) sowohl Singletons, als auch rein statische Klassen. Wenn man die Tests in Random-Reihenfolge ausführen lässt gibt es Kombinationen in denen die Tests laufen und manchmal geht es einfach nicht, weil irgendwer nicht daran gedacht hat, dass eben "reinitialisiert" werden muss.
Wenn man nur sauber testbare Klassen nutzt kann so etwas nicht passieren, da der Test niemals laufen wird ohne eine saubere Umgebung zu initialisieren.
Wenn man "Singletons" benötigt sollte man Dependency Injection Frameworks einsetzen (die für C++ sind leider nicht ganz so hübsch), denn das Problem ansich ist nicht der Wunsch nach einer Klasse mit genau einer Instanz, sondern das Singleton-Pattern (nach Gang-Of-Four) selber. Bei DI kümmert sich der Container darum, dass du innerhalb dieses Containers immer die selbe Instanz bekommst, ein paralleler DI-Container kann aber eine andere Instanz besitzen (wenn man z.B. Tests parallel starten lässt). Der Effekt für die Anwendung ist der Selbe, die Implementierung aber sauber und jederzeit testbar (und bringt Modularisierung und Dynamik in die Anwendung).