Download (direct link):
20 return theList;
Listing 14.3 GoodNavigationUtils.java (listCategories)
Notice in this example we are calling the getText() method on the Element returned in the Iterator. The returned String is then added to the HashSet.
An interesting development has evolved in the Java Community Process program (JCP). JSR 14, "Add Generic Types to the Java Programming Language," offers a
Avoiding Singleton Pitfalls 117
mechanism for providing parameterized classes (JSR stands for "Java Specification Request"). In this case, we have a List being returned to us, which we were unable to determine what type was in the list without closely consulting the API documentation. Of course, since all code is well documented in excruciating detail, we always know the types that are returned to us. In reality, the only documentation on which you can ever truly count (and frequently the only documentation that is read) is the method signature. Of course, if you were up on XML libraries, you would understand that a method called selectNodes is going to return Node objects.
This gets to the essence of the problem: The Collection classes are a very popular feature in the Java platform. Their power, efficiency, and flexibility are highly valued. However, as this example has shown, it is very difficult to know precisely how collections are handled. This requires that numerous casts and type checks are needed in order to handle something generically.
That is what JSR 14 hopes to accomplish. Now, you would be able to pass a type to the List class. For example, you could declare a vector like this:
Vector<String> x = new Vector<String>();
Generics are a feature to be added to the Java 2 Standard Edition 1.5, code-named "Tiger." Until then, developers will have to be aware of what types are being held in their collections.
Item 15: Avoiding Singleton Pitfalls
As programmers, we love design patterns! They allow us to use repeatable solutions to problems, and they offer us an easy way to communicate in software engineering projects. Used wisely, these patterns offer us the capability to quickly build elegant, flexible designs. Using them without fully understanding their purpose and impact could lead to a brittle software architecture. More importantly, creating an incorrect implementation of existing patterns could lead to disastrous results.
The Singleton design pattern, presented by Gamma, Helm, Johnson, and Vlissides in Design Patterns: Elements of Reusable Software, is a creational pattern that ensures that a class has one instance and provides a global point of access to it.4 In the Java programming language, a correct implementation of a Singleton ensures that there will be one instance of a class per JVM. There are many Singleton classes throughout the Java API itself, with a few examples being java.util.Calendar and java.util.DateFormat. The Singleton is useful in cases where you want a single point of access to a resource. In Item 32, we created a Singleton class that was a single point of access to a database. Listings 15.1 and 15.2 show two common ways of implementing a Singleton class. The constructors in both classes are private, so that only the static getInstance() method can instantiate the class. In Listing 15.1, the Singleton's constructor is called when the class is first loaded, on line 4. When a class calls the getInstance() method shown in lines 16 to 18, the static m_instance variable is returned.
4 Gamma, Helm, Johnson, Vlissides, Design Patterns: Elements of Reusable Software, Addison-Wesley, Reading, Massachusetts, 1984.
118 Item 15
01: public class ClassLoadSingleton
03: //called at class-load time
04: private static ClassLoadSingleton
05: m_instance = new ClassLoadSingleton();
07: private ClassLoadSingleton()
09: //implementation details go here
13: * point of entry to this class
15: public static ClassLoadSingleton getInstance()
17: return m_instance;
Listing 15.1 Singleton instantiated at class loading time
Listing 15.2 shows a different approach. Instead of calling the constructor at class
load time, the class uses lazy instantiation—that is, the constructor is not called until
getInstance() is called the first time. Lines 14 to 20 of Listing 15.2 show the logic of
returning the FirstCallSingleton class from the getInstance() method.
01: public class FirstCallSingleton
04: private static FirstCallSingleton m_instance = null;
06: private FirstCallSingleton()
08: //implementation details go here
12: * point of entry to this class
14: public static synchronized FirstCallSingleton getInstance()
16: if (m_instance == null)
17: m_instance = new FirstCallSingleton();
Listing 15.2 Singleton instantiated at first call
Avoiding Singleton Pitfalls 119
19: return m_instance;
Listing 15.2 (continued)