You are on page 1of 13

Discover the Design Patterns You're Already Using in

the .NET Framework

Microsoft has placed increasing emphasis on design patterns. If you are unfamiliar with patterns,
suddenly being inundated with new terms and foreign-looking UML diagrams can be overwhelming. This
emphasis on patterns, however, doesn't represent a shift in methodology so much as a change in
vocabulary. The Microsoft .NET Framework base class library (BCL) already makes extensive use of
patterns, and you are probably familiar with the most common ones, even though you might not realize it
yet.
In this article, I'll cover a basic overview of several common design patterns and how they are used in
the BCL and other areas of the .NET Framework. In doing so, you can discover some of the motivation for
why the Framework is designed the way it is, as well as make the abstract concepts of the patterns
themselves more intuitively understandable.
Most of the patterns I'll be covering come from the canonical reference, Design Patterns by Erich
Gamma, Richard Helm, Ralph Johnson, and John Vlissides, (Addison-Wesley, 1995). These authors are
collectively known as the Gang of Four. The Gang of Four didn't invent these patterns, but they
documented and formalized the good work others had been doing since the beginning of software
development.
If you are already familiar with some of these patterns, feel free to read about those you aren't familiar
with, since each section is relatively independent. The section on ASP.NET-related patterns requires
familiarity with the request pipeline, a basic overview of which is provided in that section.
Within the .NET Framework, the use of some patterns is so prevalent that they have been built into
programming languages themselves, instead of just represented by the class libraries. The first two
patterns I will discuss, the Observer and the Iterator, are supported by various language features of both
C# and Visual Basic .NET. As you will see, they are an integral part of many common programming tasks.

Observer Pattern
Good object-oriented design emphasizes both encapsulation and loose coupling. In other words, classes
should keep internal details private and also minimize their strict dependencies. In most applications,
classes don't work in isolation; they interact with many other classes. A common scenario of class
interaction occurs when one class (the Observer) needs to be notified when something changes in another
(the Subject). For example, several Windows Forms controls might need to update their display after a
button is clicked. A simple solution would be to have the Subject call a specific method of the Observer
whenever a change in state occurs. This introduces a host of problems, however. Now, since the Subject
needs to know which method to call, it is tightly coupled to that specific Observer. Furthermore, if you

need to add more than one Observer, you have to continue to add code for each method call to the
Subject. If the number of Observers changes dynamically, this gets even more complex. You'll quickly end
up with a brittle mess that's difficult to maintain.
Applying the Observer pattern helps to resolve this problem efficiently. You can decouple the Subject
from the Observers so that Observers of any variety can easily be added and removed, at both design
time and run time. The Subject maintains a list of interested Observers. Each time the Subject's state
changes, it calls the Notify method on each Observer. Figure 1 shows a sample implementation. All
classes designed to act as Observers implement the ICanonicalObserver interface, and all Subjects must
derive from CanonicalSubjectBase. If a new Observer wants to monitor a Subject, the Add method easily
handles this without having to change any code in the Subject class. Note also that each Subject only
directly depends on the ICanonicalObserver interface, not any specific Observer.
While the Gang of Four's Observer pattern solves some of these problems, there are still some
roadblocks, since subjects must inherit from a specific base class and Observers must implement a special
interface. Thinking back to the Windows Forms button example, a solution emerges. The .NET Framework
introduces delegates and events to solve these problems. If you have done any programming for ASP.NET
or Windows Forms, then you have probably worked with events and event handlers. Events act as the
Subject, while delegates act as Observers. Figure 2 shows an example of the Observer pattern, making
use of events.
The Windows Forms Button control exposes a Click event which gets raised whenever the button is
clicked. Any class designed to react to this event just needs to register a delegate with that event. The
Button class doesn't depend on any of the potential Observers, and each Observer only needs to know the
correct type of the delegate for the event (EventHandler, in this case). Since EventHandler is a delegate
type and not an interface, each Observer doesn't need to implement an extra interface. Assuming it
already contains a method with a compatible signature, it only needs to register that method with the
event of the Subject. Through delegates and events, the Observer pattern lets you decouple Subjects and
their Observers.
Back to Contents

Iterator Pattern
Many programming tasks involve manipulating collections of objects. Whether these collections are
simple lists or something more complex such as binary trees, you'll often need some way to get access to
each object in the collection. In fact, depending on the collection, you may want several ways to access
each object such as front to back, back to front, preorder or postorder. To keep the collection simple, the
traversal code itself is often in its own class.

One of the most basic ways to store a list of objects is in an array. Array types are built into both Visual
Basic .NET and C#. Both languages also have a loop structure that aids in iterating over arrays: foreach in
C# and For Each in Visual Basic .NET. Here's an easy example of iterating over arrays:
int[] values = new int[] {1, 2, 3, 4, 5};
foreach(int i in values)
{
Console.Write(i.ToString() + " ");
}

These statements make use of the iterator for the array behind the scenes. All you need to know is that
you are guaranteed to have the loop run exactly once for each item in the array.
To make those statements work, the object referenced in the In expression must implement
IEnumerable. Any collection of objects that implements the IEnumerable interface can be traversed
(enumerated). This interface has a single method, GetEnumerator, that returns an object which
implements IEnumerator. The IEnumerator class contains the code necessary to iterate through the
collection. It has a property for the current object (Current) and methods to advance to the next object as
well as start over (MoveNext, and Reset). All of the collection classes in the System.Collections
namespace, as well as arrays, implement IEnumerable and can therefore be iterated over.
If you examine the Microsoft intermediate language (MSIL) generated by the C# compiler for any code
that uses foreach, you can see that in most cases it just uses the IEnumerator to do the iteration (certain
types, such as arrays and strings, are special cased by the compiler). Here you can see the IEnumerator
approach for iterating over the same array shown previously:
int[] values = new int[] {1, 2, 3, 4, 5};
IEnumerator e = ((IEnumerable)values).GetEnumerator();
while(e.MoveNext())
{
Console.Write(e.Current.ToString() + " ");
}

The .NET Framework uses the IEnumerable and IEnumerator interfaces to implement the Iterator
pattern. The Iterator pattern lets you easily traverse a collection without exposing the inner workings of
that collection. An Iterator class, an implementer of IEnumerator, is a separate class from the collection,
which implements IEnumerable. The Iterator class maintains the state of the traversal (including what the

current item is and whether or not there are more items to be traversed) outside of the collection itself.
The algorithm for the traversal is contained in the Iterator as well. This way you can simultaneously have
multiple Iterators, each traversing the same collection in wildly different ways, without adding any
complexity to the collection class itself.
Back to Contents

Decorator Pattern
Any useful executable program involves either reading input, writing output, or both. Regardless of the
source of the data being read or written, it can be treated abstractly as a sequence of bytes. .NET uses
the System.IO.Stream class to represent this abstraction. Whether the data involves characters in a text
file, TCP/IP network traffic, or something else entirely, chances are you will have access to it via a Stream.
Since the class for working with file data (FileStream) and the class for working with network traffic
(NetworkStream) both inherit from Stream, you can easily write code that processes the data independent
of its origins. Here's a method for printing out some bytes from a Stream to the console:
public static void PrintBytes(Stream s)
{
int b;
while((b = fs.ReadByte()) >= 0)
{
Console.Write(b + " ");
}
}

Reading a single byte at a time is typically not the most efficient way to access a stream. For example,
hard drives are capable of (and optimized for) reading continuous blocks of data from the disk in a big
chunk. If you know you are going to be reading several characters, it is better to read a chunk from the
disk all at once and then consume the chunk from memory byte by byte. The Framework includes the
BufferedStream class for doing just that. The constructor for BufferedStream takes as the parameter
whatever stream you would like buffered access to. BufferedStream overrides the main methods of
Stream, such as Read and Write, to provide more functionality. Since it is still a child class of Stream, you
can use it the same as any other Stream (note that FileStream includes its own buffering capabilities).
Similarly, you can use System.Security.Cryptography.CryptoStream to encrypt and decrypt Streams on the

fly, without the rest of the application needing to know anything more than the fact that it is a Stream.
Figure 3 shows several calls to my printing method using different Streams.

Figure 4 Using the Decorator Pattern


This ability to dynamically attach new functionality to objects transparently using composition is an
example of the Decorator pattern, as shown in Figure 4. Given any instance of Stream, you can add the
capability for buffered access by wrapping it in a BufferedStream, without changing the interface to the
data. Since you are just composing objects, this can be done at run time, rather than using a technique
like inheritance, which is a compile-time decision. The core functionality is defined either by an interface or
by an abstract class (like Stream) from which all the Decorators derive. The Decorators themselves
implement (or override) the methods in the interface (or base class) to provide the extra functionality.
BufferedStream, for example, overrides Read to read from a buffer fed by the wrapped Stream, instead of
reading from that Stream directly. As Figure 3 illustrates, any composition of Decorators, no matter how
complex, can still be used as if it were only the base class.
Back to Contents

Adapter Pattern
One of the strengths of the .NET Framework is backward compatibility. From .NET-based code you can
easily call legacy COM objects and vice versa. In order to use a COM component in your project, all you
have to do is add a reference to it via the Add Reference dialog in Visual Studio .NET. Behind the scenes,
Visual Studio .NET invokes the tlbimp.exe tool to create a Runtime Callable Wrapper (RCW) class,
contained in an interop assembly. Once the reference has been added (and the interop assembly has been
generated for you), the COM component can be used like any other class in managed code. If you were
looking at code someone else had written without seeing the list of references (and without examining
metadata associated with the classes or their implementation), you would be unable to tell which classes
were written in a .NET-targeted language and which were COM components.
The magic that makes this happen is contained in the RCW. COM components have different error
handling mechanisms and also make use of different data types. For example, strings in the .NET
Framework use the System.String class while COM might use a BSTR. When calling a COM component

with a string parameter from .NET-based code, though, you can pass in a System.String just like you
would to any other similar managed code method. Inside the RCW, this System.String is converted into a
format that the COM component expects, like a BSTR, before the COM call is made. Similarly, a method
call on a COM component typically returns an HRESULT to indicate success or failure. When a COM method
call returns an HRESULT that indicates that the call failed, the RCW turns this into an exception (by
default), so it can be handled like all other managed code errors.
By allowing managed classes and COM components to interact despite their interface differences, RCWs
are an example of the Adapter pattern. The Adapter pattern lets you adapt one interface to another. COM
doesn't understand the System.String class, so the RCW adapts it to something that it can understand.
Even though you can't change how a legacy component works, you can still interact with it. Adapters are
frequently used like this.
The Adapter class itself wraps an Adaptee, translating all calls from the client into the appropriate
format and sequence of calls. Though this sounds similar to the Decorator, there are several key
differences. With a Decorator, the interfaces of the objects you're composing are the same, while the
entire point of an Adapter is to allow you to change interfaces.Adapters also have a definite sequence to
them; the Adaptee must be contained by the Adapter. A Decorator class doesn't need to know whether it
is wrapped by 1 or 500 other classes, since the interfaces are all the same. As a result, the use of
Decorators can be transparent to the application, while the use of Adapter cannot.
Back to Contents

Factory Pattern
There are many cases in the Framework where you can obtain a new instance of a struct or class
without calling its constructor yourself. The System.Convert class contains a host of static methods that
work like this. To convert an integer to a Boolean, for example, you can call Convert.ToBoolean and pass in
the integer. The return value of this method call is a new Boolean set to "true" if the integer was non-zero
and "false" otherwise. The Convert class creates the Boolean for you with the correct value. Other type
conversion methods work similarly. The Parse methods on Int32 and Double return new instances of those
objects set to the appropriate value given only a string.
This strategy for creating new object instances is known as a Factory pattern. Rather than invoking the
object's constructor, you can ask the object factory to create the instance for you. That way, the factory
class can hide the complexity of object creation (like how to parse a Double out of a string). If you wanted
to change the details of creating the object, you'd only have to change the factory itself; you would not
have to change every single place in the code where the constructor is called.
These type conversion methods are one variant of this pattern, since you're not required to use the
factory to create the objects in question. A more pure example of this pattern is the
System.Net.WebRequest class, used to make a request and receive a response from a resource on the

Internet. FTP, HTTP, and file system requests are supported by default. To create a request, call the Create
method and pass in a URI. The Create method itself determines the appropriate protocol for the request
and returns the appropriate subclass of WebRequest: HttpWebRequest, FtpWebRequest (new to the .NET
Framework 2.0), or FileWebRequest. The caller doesn't need to know the specifics of each protocol, only
how to invoke the factory and work with the WebRequest that gets returned. If the URI changes from an
HTTP address to an FTP address, the code won't have to change at all. This is another common use of the
Factory pattern. The parent class acts as a factory and returns a specific derived class based on
parameters the client passes in. As in the WebRequest example, this hides the complexity of selecting an
appropriate derived class from the caller.
Back to Contents

Strategy Pattern
Both Array and ArrayList provide the capability to sort the objects contained in the collection via the
Sort method. In fact, ArrayList.Sort just calls Sort on the underlying array. These methods use the
QuickSort algorithm. By default, the Sort method will use the IComparable implementation for each
element to handle the comparisons necessary for sorting. Sometimes, though, it is useful to sort the same
list in different ways. For example, arrays of strings might be sorted with or without case sensitivity. To
accomplish this, an overload of Sort exists that takes an IComparer as a parameter; IComparer.Compare
is then used for the comparisons. This overload allows users of the class to use any of the built-in
IComparers or any of their own making, without having to change or even know the implementation
details of Array, ArrayList, or the QuickSort algorithm.
Leaving the choice of comparison algorithm up to the user of the class like this is an example of the
Strategy pattern. The use of Strategy lets a variety of different algorithms be used interchangeably.
QuickSort itself only requires a way to compare objects to each other. By calling Compare through a
provided interface, the caller is free to substitute whatever particular comparison algorithm fits its specific
needs. The code for the QuickSort can remain unchanged.

Figure 5 Strategy in Action


One of the new generic collections in version 2.0 of the .NET Framework, List<T>, also makes heavy
use of the Strategy pattern, shown in Figure 5. In addition to the updated Sort method, the find-related
methods, BinarySearch, and others all take parameters that allow parts of the respective algorithms to
vary based on the needs of the caller. The use of a Predicate<T> delegate in the FindAll<T> method lets
the caller use any method as a filter for the List<T> so long as it takes the appropriate object type and

returns a Boolean. Combined with anonymous methods (another new C# language feature in version 2.0),
clients can easily filter lists based on properties and methods of the objects in the list, without introducing
dependencies into the List<T> class itself. Using the Strategy pattern lets complicated processes like
sorting be easily modified to fit a caller's specific purpose, meaning you'll be able to write and maintain
less code.
Back to Contents

Composite Pattern in ASP.NET


The ASP.NET request/response pipeline is a complex system. Patterns are used in the design of the
pipeline itself and in the control architecture to effectively balance its performance with extensibility and
ease of programming. Before delving into the pipeline, however, I'll examine the patterns used in the
programming model itself.
When dealing with collections of objects, there are often operations that are appropriate for both a
single object and the entire collection. Think about an ASP.NET control. A control may be a simple single
item like a Literal, or it could be composed of a complex collection of child controls, like a DataGrid is.
Regardless, calling the Render method on either of these controls should still perform the same intuitive
function.
When each item in the collection might itself contain collections of other objects, the use of the
Composite pattern is appropriate. Composite is an easy way to represent tree-like collections without
having to treat parent and leaf nodes differently.
The canonical example of Composite relies on an abstract base class, Component, that contains both
methods for adding and removing children, and the operations common among parents and children.
ASP.NET uses this formulation exactly with System.Web.UI.Control. Control represents the Component
base class. It has operations for dealing with children (such as the child Controls property) as well as
standard operations and properties like Render and Visible. Each object, whether a primitive object (like
Literal) or a composite of several objects (like DataGrid), inherits from this base class.
Because the domain of controls is so diverse, there are several intermediate derived classes like
WebControl and BaseDataList that serve as base classes for other controls. Though these classes expose
additional properties and methods, they still retain the child management functions and core operations
inherited from Control. In fact, the use of the Composite pattern helps to hide their complexity, if desired.
Regardless of whether a control is a Literal or a DataGrid, the use of Composite means you can just call
Render and everything will sort itself out.
Back to Contents

Template Method Pattern

When the standard library of ASP.NET controls doesn't meet your needs, you have several options on
how to create your own. For simple controls that only need to be used in a single project, a user control is
often the best choice. When the control is to be used in several Web applications or requires more
functionality, a custom server control may be a better fit.
When dealing with custom controls, there are two general types: controls that combine the
functionality of several existing controls (called composite controls), and controls with a unique visual
representation. The process for creating both of these types is very similar. For composite controls, you
create a new class that inherits from one of the control base classes (like Control or WebControl) and then
override the CreateChildControls method. In this method you add the controls whose functionality you are
combining to the collection of child controls, called Controls. For other custom controls, you override
Render instead and use the HtmlTextWriter parameter to output the HTML for your control directly.
Regardless of which style of custom control you choose, you don't have to write any code to handle the
functionality that's common to all controls, like loading and saving ViewState at the right time, allowing
PostBack events to be handled, and making sure the control lifecycle events are raised in the correct
order. The main algorithm for how a control should be loaded, rendered, and unloaded is contained in the
control base class.
The specifics of your particular control are handled at well-defined places in the control algorithm (the
CreateChildControls or Render methods). This is an example of the Template Method pattern. The main
algorithm skeleton is defined in a base class and subclasses can then plug in their own details without
affecting the algorithm itself, as shown in Figure 6. A composite control and a custom control both share
the same general lifecycle, but they can end up with drastically different visual representations.

Figure 6 Template Method Pattern


This pattern is similar to the Strategy pattern. These two patterns differ in scope and in methodology.
Strategy is used to allow callers to vary an entire algorithm, like how to compare two objects, while
Template Method is used to vary steps in an algorithm. Because of this, Strategy is more coarsely grained.
There can be vast differences between different client implementations, while with Template Method the
algorithm remains fundamentally the same. The other main difference is that Strategy uses delegation
while Template Method uses inheritance. In the sorting example of Strategy, the comparison algorithm is
delegated to the IComparer parameter, but with custom controls you subclass the base and override
methods to make changes. Both, however, let you easily alter processes to fit your specific needs.
Back to Contents

Patterns in the ASP.NET Pipeline

When a client requests an ASPX page from the Web server, the request travels through many steps
before ultimately ending up as HTML displayed by the client's browser. First, the request is processed by
IIS and routed to the appropriate ISAPI extension. The ISAPI extension for ASP.NET (aspnet_isapi.dll)
routes the request to the ASP.NET worker process.

Figure 7 ASP.NET Request Pipeline


At this point, the request begins to interact with classes that you are used to dealing with. The request
is passed to an HttpApplication. Usually this is the class created in the codebehind file for Global.asax. The
HttpApplication then passes the request through any number of HTTP Modules. These classes implement
the IHttpModule interface and have a chance to modify the request (or even halt the processing of it)
before it gets passed on to the next module. ASP.NET provides some standard modules which provide
functionality you're probably familiar with, including FormsAuthenticationModule,
PassportAuthenticationModule, WindowsAuthenticationModule, and SessionStateModule, all of which
provide exactly the functionality that their names imply.
Ultimately, the request ends up at an IHttpHandler, the most common of which is System.Web.UI.Page.
Inside the IHttpHandler.ProcessRequest method, Page raises appropriate events (like Init, Load, and
Render), handles ViewState, and provides the programming model for ASP.NET. Figure 7 shows an outline
of this process.
Several of the patterns employed by this process are more thoroughly documented in another standard
reference for patterns, Martin Fowler's Patterns of Enterprise Application Architecture (Addison-Wesley,
2002).
Back to Contents

Intercepting Filter Pattern


Once a request has made it into an HttpApplication, it passes through any number of IHttpModules.
Each module is independent and has only a limited amount of control over the order in which it is invoked.
The HttpApplication class exposes a sequence of events that get raised as the request makes its way
through processing. These events include BeginRequest, AuthenticateRequest, AuthorizeRequest, and

EndRequest. When the HttpApplication loads a module, it calls the Init method of the IHttpModule
interface, allowing the module to register for any of the events it cares about. As a given request is
handled, the events are raised in the appropriate order and all registered modules get a chance to interact
with the request. The module can therefore control the stage at which it gets invoked, but not the exact
order within that stage.
These modules are an example of the Intercepting Filter pattern. This pattern represents a chain of
filters that are each in turn given a chance to modify a request (or message) that passes through them.
Figure 8 shows a simplified flow diagram of this process. The key ideas of this pattern are that the filters
are independent; filters can modify the request as it passes through.

Figure 8 Request Flow


There are several different implementation variations of the Intercepting Filter pattern, one of which is
the event-based model employed by ASP.NET. A simpler variant involves maintaining a list of filters and
iterating over it, invoking a method on each one in turn. This is how the Web Services Enhancements
(WSE) for ASP.NET Web services uses this pattern. Each filter either extends SoapInputFilter (for request
messages) or SoapOutputFilter (for responses), overriding the ProcessMessage method to perform the
work of the filter.
Another option is to implement Intercepting Filter via the Decorator pattern. Then each filter would
wrap its successor, performing preprocessing, invoking the successor, and then performing postprocessing. The chain would be built using recursive composition, from back to front. This pattern is used
to implement .NET Remoting channel sinks.
Regardless of implementation, the result is a dynamically configurable chain of independent filters.
Since they are independent, these filters can easily be reordered and reused in other applications.
Common tasks like authentication or logging can be encapsulated in a filter and used over and over. These
tasks can then be handled by the filter chain before a request even reaches the HttpHandler, keeping the
handler code cleaner.
Back to Contents

Page Controller Pattern


System.Web.UI.Page implements a core part of the programming model for ASP.NET. Whenever you
want to add a logical page to a Web application, you can create a Web Form (represented by an ASPX file
and its codebehind). You can then write code to handle the specific demands of the new page, whether
through handling page-level events, displaying a set of controls, or loading and manipulating data. Each

logical page in the application has a corresponding Web Form that controls its behavior and regulates its
presentation.
The practice of having one controller for each logical page is an example of the Page Controller pattern.
This idea is fundamental to ASP.NET. When a logical page is requested via its URI, the ASP.NET runtime
resolves the address to the corresponding subclass of Page and uses that class to handle the request. All
the details about what a page looks like, what user input it can handle, and how it responds to that input
are contained in a single place. When a logical page in the application requires changes, no other pages
are affected. It's an abstraction that's so common we don't even think about it.
One of the drawbacks usually associated with the pure implementation of Page Controller is that
common code must be repeated for each page. ASP.NET avoids this drawback by including other patterns
in the pipeline implementation, as well as providing System.Web.UI.Page as a common base class for all
Page Controllers. Cross-cutting concerns like authentication and session state are handled by the
HttpModule Intercepting Filters and raising page lifecycle events, and other activities, are handled by the
base class.
Back to Contents

Other Web Presentation Patterns in ASP.NET


In addition to Intercepting Filter and Page Controller, ASP.NET makes use of variations of several other
Web presentation patterns. When ASP.NET determines which HttpHandler to pass a request to, it uses
something similar to a Front Controller. Front Controller is characterized by a single handler for all
requests (like System.Web.UI.Page). Once the request reaches the Page class, though, the Page Controller
pattern takes over.
Within the ASP.NET implementation of Page Controller, there are elements of the Model View Controller
pattern. Model View Controller separates the model (business objects, data, and processes) from the view
(the display of information). The controller responds to user input and updates the model and view.
Roughly speaking, an ASPX page represents the View while its codebehind file represents a hybrid ModelController. If you were to pull all business and data-related code out of the codebehind and leave only
event handling code, this would turn the codebehind into a pure Controller while the new class containing
the business logic would be the Model.
Since these variations diverge from the canonical form of the patterns, they won't be covered here.
Martin Fowler's book and the Microsoft Patterns site are good sources for more discussion.
Back to Contents

Conclusion
Now that I have examined instances of common patterns in use throughout the .NET Framework and
BCL, it should be even easier to recognize those same patterns in code you work with every day. Hopefully

highlighting the design patterns underlying common classes and functionality has given you a better sense
of what those patterns are and the benefits they provide. Trying to imagine UI programming without the
Observer pattern or collections without an Iterator shows how indispensable these frameworks really are.
Once you understand what each does, it becomes another valuable tool to add to your toolbox.

You might also like