You could create normal classes then due to the usage architecture of your classes, only one instance of each class should ever reasonably be created. This is using dependency injection to replace singletons.
Some factory/main-like method would handle the loading/creation and passing of these instances to each of their dependents. No instance should ever need to exist as a singleton instance, but rather as a variable within a function.
// No need for singleton patterns, // but only one instance is ever created // by the program's main function. int main() { Info info = Info::LoadFromSystem("info.xml"); A a = A::CreateFromInfo(&info); B b = B::CreateFromInfo(&info); C c = C::CreateFromInfo(&info); // dependency injection (use pointers or references, same essential thing) Server1 server1 = new Server1(&a); Server2 server2 = new Server2(&server1, &a, &b, &c); server1.Run(); server2.Run(); // cleanup return 0; }
Meeting Singletons Halfway
A common pattern often used in frameworks is the "default instance" style of singleton. This frees up the class to be reinstantiated for other simultaneous use but creates a default instance that can be relied upon for most cases.
In C++, the example might be like this, although it creates a requirement to handle shutdown of the app and destroy the default instance:
class MostlySingle { private: static MostlySingle *_default = NULL; public: static MostlySingle *createDefault(Info &info) { if (_default != NULL) { // throw exception } _default = new MostlySingle(info); return _default; } static MostlySingle *default() { return _default; } static void destroyDefault() { delete _default; _default = NULL; } } int main() { // app startup MostlySingle::createDefault(Info::default()); auto instance = MostlySingle::default(); instance.send("Hello, world!"); // app shutdown MostlySingle::destroyDefault(); return 0; }