MsCorEE

JeffGonzalez : IScalable

Provider, Strategy, Adapter pattern discussion

Some of my coworkers and I were having a discussion today regarding the aforementioned patterns.  First we debated the validity of the Provider pattern actually being considered a pattern, or if it was really just a renamed Strategy or Adapter pattern.

Here is some background on the patterns for reference.  I took my definitions from DOFactory.  I use their site quite a bit when referencing patterns or when I need a refresher.

Adapter
Converts the interface of a class into another interface clients expect.  Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.  Forgive the Java naming conventions.  =P

Suppose you have two separate interfaces:

interface Iterator
{
   HasNext()
   Next()
   Remove()
}
interface Enumeration
{
   HasMoreElements()
   NextElement()
}

These two interfaces are pretty similar, but they have different method names and Iterator is read-write while Enumeration is read-only.   For my example, I want to adapt Enumeration to the Iterator interface.  In Java most things use the Iterator interface now, but it is possible that some legacy code might still be using the Enumeration interface.  This pattern allows us to use the Iterator interface, but provides a method to interoperate with the Enumeration interface as well.

public class EnumerationIterator : Iterator
{
private Enumeration _Enumeration;
public EnumerationIterator(Enumeration enum)
{
   _Enumeration = enum;
}
public Boolean HasNext() { return enum.HasMoreElements(); }
public Object Next() { return enum.NextElement(); }
public void Remove() { throw new NotImplementedException(); }
}

Strategy
Define a family of algorithms, encapsulate each one, and make them interchangeable.  Strategy lets the algorithm vary independently from the clients that use it.
 
IComparable is a good example of the Strategy pattern.  IComparable defines a single member called CompareTo (Object o).  This allows different classes to define different strategies for comparison.  As long as the class implements IComparable and the CompareTo member, the implementation is up to the class itself.

Provider
I couldn't exactly find the definition of this pattern on DOFactory, so I looked at Rob Howard's article on MSDN.  He states, "Defined, a provider is simply a contract between an API and the Business Logic/Data Abstraction Layer. The provider is the implementation of the API separate from the API itself."

This pattern was advocated pretty heavily by the folks at Microsoft during the .NET 2.0 framework development cycle.  The Membership API is a good example of the concrete implementation.  The Membership API contains several methods and properties like CreateUser, GetAllUsers, and ValidateUser.   By default the Membership API uses the built in providers that Microsoft developed.  They realized that Joe Developer might want to store his users in SQL Server, and Josie Developer might want to talk to Active Directory for her users.  To that end, they created the provider pattern.  I won't rehash the whole thing, but for clarification check out Rob's article.

I think the provider pattern also happens to have a bit of Dependency Injection/Inversion of Control flavor to it.  It doesn't specifically use a container technology like Windsor or Spring.NET, but by preferring configuration over convention it allows the developer to configure their API to use a specific provider without a huge amount of coding.

Discussion
Our conversation today centered around whether the Provider pattern is a unique pattern or just a representation of the Strategy/Adapter patterns.  Both Strategy and Adapter seem very similar on the surface, but if you look deeper, they seem to be diametrically opposed to each other.  Implementation of the Strategy pattern seems like part of the design process, prior to coding.  You establish a need for an interchangeable algorithm and create an interface that supports it. Then you code the different implementations for each strategy.  On the other hand, the Adapter pattern seems to be sort of an afterthought. You have an established interface that maybe is used in a lot of places, but you want to adapt it to another more current interface. This is a pretty common scenario when dealing with legacy code.

I was advocating the idea of the Provider pattern really being a Strategy.  As I mentioned earlier, the Membership API might have a different strategy for storing user data between two developers.  One developer uses SQL Server and another uses Active Directory.  My boss Shannon (sorry, no blog…yet) stated that you could argue that the Membership API was adapting each of those implementations to fit the needs of the developer.
 
We commented that depending on your point of view the Provider pattern could fit either of those patterns, it just depends on when and where you start.

What do you think?

Comments

No Comments