Agile Principles, Patterns, and Practices in C#
| SINGLETON is a very simple pattern.[2] The test case in Listing 24-1 shows how it should work. The first test function shows that the Singleton instance is accessed through the public static method Instance and that if Instance is called multiple times, a reference to the exact same instance is returned each time. The second test case shows that the Singleton class has no public constructors, so there is no way for anyone to create an instance without using the Instance method. [2] [GOF95], p. 127 Listing 24-1. Singleton test case
This test case is a specification for the SINGLETON pattern and leads directly to the code shown in Listing 24-2. By inspecting this code, it should be clear that there can never be more than one instance of the Singleton class within the scope of the static variable Singleton.theInstance. Listing 24-2. Singleton implementation
Benefits
Costs
SINGLETON in Action
Assume that we have a Web-based system that allows users to log in to secure areas of a Web server. Such a system will have a database containing user names, passwords, and other user attributes. Assume further that the database is accessed through a third-party API. We could access the database directly in every module that needed to read and write a user. However, this would scatter usage of the third-party API throughout the code and would leave us no place to enforce access or structure conventions. A better solution is to use the FACADE pattern and create a UserDatabase class that provides methods for reading and writing User objects.[3] These methods access the third-party API of the database, translating between User objects and the tables and rows of the database. Within the UserDatabase, we can enforce conventions of structure and access. For example, we can guarantee that no User record gets written unless it has a nonblank username. Or, we can serialize access to a User record, making sure that two modules cannot simultaneously read and write it. [3] This special form of the FACADE pattern is known as a GATEWAY. For a detailed discussion of GATEWAYs, see [Fowler03]. The code in Listings 24-3 and 24-4 show a SINGLETON solution. The SINGLETON class is named UserDatabaseSource and implements the UserDatabase interface. Note that the static Instance() method does not have the traditional if statement to protect against multiple creations. Instead, it takes advantage of the .NET initialization facility. Listing 24-3. UserDatabase interface
Listing 24-4. UserDatabase Singleton
This is an extremely common use of the SINGLETON pattern. It ensures that all database access will be through a single instance of UserDatabaseSource. This makes it easy to put checks, counters, and locks in UserDatabaseSource to enforce the access and structure conventions mentioned earlier. |
Категории