The singleton pattern, as described in the gang of four book, as it is mostly implemented in Java, can indeed be considered an antipattern. This includes static accessors, enum singletons, and so on, which are at most singletons in the scope of a single class loader.
However, if you write Java software today, you'll probably not start out with public static void main()
and roll your own from there. Usually, you'll be using some kind of container to perform the setup of your application, and there is your alternative. In CDI, you declare a bean as @ApplicationScoped
, and there's a similar scope in Spring.
Still a singleton, but not a roll-your-own implementation. And this is quite OKish, provided that you are prepared to deal with global state, which this still represents.
Note however, that this kind of singleon is still "once per container", so the setup is not scalable. If you intend to run multiple instances of your application together in a cluster, you need to find a different solution.