Cardinality: Would vary by object, I guess. An object that enforces cardinality appropriate to its function and limitations and within appropriate temporal limits. Note that one should tread very carefully with this sort of thing. Cardinality enforced in code ('hard coded') is likely to be quite vexing. There do not appear to be any convincing requirements for this anywhere that I can find. Perhaps someone looking at this can throw in some ideas.
Context information from beyond the local scope: Context object handed down from a parent, caller, etc. This notion has been criticised (perhaps not unfairly) as having its own problems. However, I would suggest that the cure is definitely better than the disease. A context object or objects could be abused. It could become cumbersome. However, that is not of necessity from the nature of a context object. On the other hand, the very intent of 'out of scope' visibility is problematic. There is no way to code around the 'breakage' of that pattern. It defeats scoping rules. Chances are very good that the language designers and the compiler writers are to be deferred to in their opinion that scoping is a GoodThing(TM).
Benefits of a context object over SingletonPattern:
Does not conjoin context with cardinality. Passes out of scope naturally according the rules of the language.
[GuyWhoReopenedTheSingletonCanOfWorms]
Exercise for the critics of SingletonPattern. If you are familiar with Java, go to your local JDK installation, and you'll find a src.jar . Unzip it and find every instance of the singleton pattern. Restructure the code along the guidelines here presented, and compile it again. Now download a non-trivial Java project, say JakartaTomcat? and try to compile it with the new Java class library -- obviously it won't but you'll get a list of compilation errors. Fix those by passing all kinds of context objects along the lines you mentioned here. Report back the results. Don't rush it, just take your time cause you'll need it :) --CostinCozianu
Wouldn't the exercise suggested above merely confirm the dreadful problems with the SingletonPattern? I think everyone would agree that the exercise above would be torture. That is because the SingletonPattern demonstrates its deficiencies in spades in that scenario. Yes, it would be very, very difficult to refactor the above. The reason is that the Singleton Pattern by its nature bleeds well across boundaries it has no business crossing. There is a name for fragile code like that -- 'spaghetti code'. It gets that way due to violating scoping rules and causing 'hard-coded' assumptions to creep into one part of the code and bleed across to another. Were the code to be free of Singletons, one might find the exercise much easier. The argument above seems to follow the lines of 'Singletons are so bad you should not touch them'. I agree. Had they not been touched (used) in the first place, the exercise might be a trivial one.
It's difficult to argue that removing all Singletons from code where no Singleton exists would not be a trivial task. --PatrickMcCormick?
Perhaps instead of replacing the singleton pattern entirely, the class/object factories should keep the objects and enforce singleton/duality rules at that level. If the singleton-ness of the class/object is controlled in that fashion, then you don't cross the boundaries it should not cross. It is an invocation boundary so it should be relegated to a sub-pattern of an invocation such as FactoryPattern. --WyattMatthews
If we are to replace Singletons (and there are plenty of reasons to do so), we honestly should be looking at the problem that the SingletonPattern solves and finding a more general, better solution to that same problem. I'm interested, particularly, in distributed programming... and attempting to understand what 'singleton' means in the distributed context is rather difficult. Is a singleton local to a single execution of a program on one machine? That seems a rather arbitrary distinction with no founding at all in mathematics, and the cardinality isn't exactly 'one' in the distributed context. I tend to think that the ultimate 'SingletonReplacement?' is to replace singletons with shared services... whether it be shared to agents within a single program in a single execution on a single machine or shared across a thousand computers. A 'singleton' in this case would be determined at compile-time or execution-time attachment to a single service to fulfill a certain role. The existing SingletonPattern objects all qualify for this greater concept as specialized forms... as do statically allocated classes and libraries that hook into certain services (e.g. malloc).