Singleton Pattern

By Michael Flanakin @ 7:17 AM :: 707 Views :: 0 Comments :: .NET 1.x, .NET 2.0, Patterns, Proven Practices :: Digg it!

Real World Scenario

Imagine a system which must process long-running queries. The system needs to keep track of what queries are currently being executed and have the ability to report back the status of a specific query. To do this, there needs to be a single place to store and manage the state of each query. This state management service will be implemented using a singleton.

Since there are many ways to manage state, we'll make use of a couple other patterns and have a state provider, based on which we can implement several different state management schemes. This will include an IStateProvider interface to define what it means to be a state provider and a few sample implementations. I've scaled back this solution for simplicity, but it should get the point across. In the same essence of simplicity, I'm not going to dig into the complete code sample here, but it is available for download below.

Singleton Pattern Real World Example Class Diagram

When the client calls the QueryRunner.ExecuteAsync() method, an instance of the configured state provider must be retrieved, with which the query will be persisted. Then, the query must be executed asynchronously. I didn't do this part because it wasn't really necessary to show the usage of the state provider singleton.

/// <summary>
/// Executes the specified <paramref name="sql"/> asynchronously.
/// </summary>
/// <param name="sql">SQL statement to execute.</param>
/// <returns>The id of the query being executed.</returns>

public static int ExecuteAsync(string sql)
{
  // validate params
  if (String.IsNullOrEmpty(sql))
    throw new ArgumentNullException("sql");
  if (!ValidateSql(sql))
    throw new ArgumentOutOfRangeException("sql", sql, "The specified SQL statement is not supported.");

  // create query
  Query query = new Query(sql);
  StateProviderFactory.Instance.Create(query);

  // TODO: Execute query asynchronously
  
  // return
  return query.Id;
}

While the query is executing, the client can check on the progress by calling the QueryRunner.IsComplete() method, which utilizes the state provider to retrieve the persisted query and see if it's still running or not.

/// <summary>
/// Retrieves a value specifying whether the query with the specified <paramref name="id"/> has completed.
/// </summary>
/// <param name="id">The unique identifier of the query.</param>
/// <returns><c>true</c> if the query has completed; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown if a query could not be found with the specified <paramref name="id"/>.</exception>

public static bool IsComplete(int id)
{
  Query query = StateProviderFactory.Instance.Get(id);
  if (query == null)
    throw new ArgumentOutOfRangeException("id", "A query with the specified id, " + id + ", could not be found.");
  else
    return query.IsComplete;
}

I imagine some people are itching to argue this solution, so let me stop you right there and say that I'm not suggesting this is the best possible solution for the problem of long-running queries. This solution was in place before I came on the scene and I simply wanted to use it as an example of using the singleton pattern in the real world. I left a lot of the code unimplemented for a few reasons, mainly because a functioning sample isn't necessary to show the use of the pattern. If someone disagrees, I guess I could put in the extra effort to flesh this out a bit more. I'll probably add to it as I write about other patterns.

Ratings

Comments

Currently, there are no comments. Be the first to post one!
Click here to post a comment



Categories Categories