Command Pattern Background
One of the most ubiquitous software patterns in existence is
the Command Pattern: “Encapsulate a request as an object, thereby
allowing for the parameterization of clients with different requests, queue or
log requests, and support undoable operations” – GOF. It is generally used
in situations where the all of the information necessary for a future call can
be ‘built up” sequentially and finally executed at a point in time in the
future – i.e. each action is state-full.
A common scenario is an object used to build up a database
request taking in several different parameters such as the database name and
location, the stored procedure name, any data that needs to be passed to the
stored procedure and possibly a transaction object. Once the command has been
constructed and all required parts are defined, it is executed, which delegates
an action to call the stored procedure on the database and return a result set
or perform some operation on an object, with the provided parameters. In the C#
world, we are talking about System.Data.DbCommand
and its concrete classes such as System.Data.SqlClient.SqlCommand
or any other database specific implementation of DbCommand (Oracle, MySql,
etc.).
Here is the basic UML diagram of the Command Pattern:
The Command Pattern typically utilizes the following actors:
- Client
– creates the command object providing the relevant information
(parameters) needed to fulfill its obligations
- Invoker
– initiates the action on the command so that it’s obligations are
fulfilled, making the decision of which of the commands actions should be
called
- Receiver
– performs the command object’s obligations, whatever they might be – i.e.
makes database call or some other action
The Command Pattern
Implemented
The scenario is this: a service exists which takes as input
a series of inputs (a query) and returns as output, the results of those inputs
as an xml stream of attributes and values. Caching at the service level and
several operations are also supported: filtering, sorting, paging, etc.
Each request varies by parameters and is encapsulated as a
query object defined by the client. This query object is simply a data
structure that contains the fields accepted optionally be the service. The
query object is executed by a command object created by the client, who
delegates control to the receiver encapsulated by it’s invoking one of its
action methods.
The following diagram illustrates the implementation:
The Command implementation is very simple. It contains an
ICommandReceiver reference and IQueryRequest reference which stores a reference
to the current query being executed. The command delegates control to the
receiver, which performs its work and returns back an IQueryResponse object
containing the results of the query.
The ContentReceiver class implements ICommandReceiver
interface and simply makes the call to the remote service via a WCF client.
This happens to be a very simplistic implementation in that much of the heavy
lifting (i.e. caching, query generation, etc.) occurs in the service. In this
case, we are simply translating a client query into a SOAP request to access
the services resources.
The client uses an IQueryRequest object to build up a set of
parameters which are consumed by the service endpoint via the command object. The
results are returned to the client with an IQueryResponse object. How the
results are used is dependent upon the client.
Finally, a simple unit test illustrating the usage: