The Pattern and Matcher classes aren't singletons, but they are examples of the more general pattern of using a
factory method. The singleton pattern is a special case of this, which is much overused and over-emphasized, and pretty much irrelevant here. Ignoring singletons, factory methods have a number of possible benefits in general, several of which are discussed in the linked article.
However, I don't think most of the points listed apply very much to Pattern. Instead I think that the main reason to use the pattern here is to allow for certain future optimizations - specifically, it's not always necessary to create a
new Pattern object. A future implementation of Pattern could keep a cache of previously-created Pattern objects, and whenever a Pattern is requested that matches a previously-created Pattern, that existing object could be returned, rather than creating a new one. In certain situations this could result in substantial benefits to performance. Admittedly, this improvement is currently hypothetical - the current JDK does
not do anything of the sort. But it could. If they had made the Pattern constructor public, then whenever someone called new Pattern(), there would
have to be a new Pattern object created. Using a factory method instead allows more flexibility for future implementations, even if that flexibility is not utilized in current implementations.
Ultimately, while I think using a factory method here was a good idea, I think that they didn't do a good job of taking this thinking as far as they could have. The fact that Pattern has a private constructor prevents alternate implementations. Pattern should have been an interface, and another class (e.g. java.util.regex.Patterns) could have provided some standard implementations. The idea of caching Pattern instances is a good one - however in some cases it would
create problems. If your program is regularly requesting completely new Pattern objects (which do not match any previous objects) then it may be a bad idea to try to keep all the previously-created Patterns in memory. So you don't want to force all users to use an implementation that caches Patterns in this way. Instead, better to have several implementations available, and let the user choose what works best for them.
As for the Matcher class, notice that contrary to what was said in the first post above, it
doesn't have a private constructor - it has a
package-elvel constructor. Nor is there a static matcher() method in Matcher - it's in Pattern. Because a Matcher really needs to be associated with a Pattern; there's no point at all in having a Matcher with no Pattern. So they put the factory method in that class - you need a Pattern before you can get a Matcher. Note that the method is not static - factory methods can be static or non-static; if they are not static then the objects they are attached to are called
factories. This is a further specialization of the factory method pattern. In turn this can be further specialized to become the
abstract factory pattern, which is
not what we have here. But it is sufficiently well-known that it seemed worth mentioning for clarity. If you google "factory method pattern" you will probably find a fair amount of material which is specific to the
abstract factory pattern, which is related, but is not strictly relevant here. So it's good to be aware that there are several levels of interrelated patterns here. Don't think that everything with the
word "factory" in it is implemented the same way.
[ November 18, 2007: Message edited by: Jim Yingst ]