Starting with version 2.0, ASP.NET comes with an extensible model that lets you unplug existing functionalities and roll your own. The model is based on client and server components (named providers) that share an interface. A primary principle of object-oriented design lies behind this model -- program to an implementation not to a class. An ad hoc design pattern turns this principle into practice -- the Strategy pattern.
Defined, the Strategy pattern indicates an expected behavior that can be implemented through a variety of interchangeable algorithms. Each application then selects the algorithm that best fits while keeping the public, observable behavior and programming API intact. The Strategy pattern is not specific of a given technology; as such, it can be applied to a variety of scenarios, including ASP.NET.
The provider model, that is so popular in ASP.NET 2.0 and newer versions, is entirely based on the ideas expressed by the Strategy pattern. Applied to an ASP.NET service such as user profiling, the Strategy pattern isolates in the replaceable algorithm the code to store and retrieve user preferences and serve them to the page through a common and unchangeable API.
The most notable feature of the Strategy pattern is that it provides an abstract way for an object to expose its internal machinery so that a client can detach the default engine and replace it with a new one. This is exactly what happens in ASP.NET for a number of services, including membership, roles and state management, user profiling, site navigation.
The ability to replace standard functionalities with external components is emerging as one of the hottest features of modern applications -- and not necessarily Web applications. Applied, the Strategy pattern takes straight to a plug-in mechanism where the client component, such as the ASP.NET HTTP runtime, sets up a factory-based system that, based on a configuration layer, creates the instance of a given type that a client will consume through an interface. This is referred to as the Plugin pattern.
From the client's perspective, the capabilities of the actual component are not relevant. All that the client cares about is whether or not the actual component supports the contracted interface.
In literature, there's another pattern with a very similar goal: the "Service Locator" pattern. A service locator is an object that knows how to retrieve all of the services that an application may need. Is there any significant difference between the Service Locator and Plugin patterns? In both cases, you have an object that a client calls to get objects that provide some known interfaces. At the end of the day, they are functionally equivalent and you can use both and be equally happy. What matters is that the resulting code can load external components and work with them effectively. The Plugin pattern exists to inject a concrete implementation where the client expects a given interface. The main purpose of the Plugin purpose is making the code extensible and flexible. The main purpose of the Service Locator, instead, is getting the lowest possible coupling between components. It represents a centralized console that an application uses to obtain all the external dependencies it needs.
Finally, dependency injection is another way of looking at things. Dependency injection revolves around the idea of the hosting environment passing instances of required services to a component. In other words, the component doesn't care about locating its own services; it receives them from the host. Dependency injection is related to the use of special frameworks that greatly simplify the application of the pattern. These frameworks go under the name of Inversion of Control frameworks. A good example is the Castle Windsor project.
Introduced as an ASP.NET specific feature, the provider model in ASP.NET 2.0 and superior is a feature that relies on the power of a number of design patterns that are applicable to custom features of ASP.NET applications and beyond.