Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

Dynamic Behavior with the Decorator Pattern

The Decorator pattern is a means to transparently add responsibilities to another object on the fly.  In some cases it’s a simpler solution than creating additional subclasses through inheritance.  A decorator is implemented by creating a class that wraps access to another class.  The decorator implements the exact same public interface as it’s inner member.  That sounds like a lot of gobbledy-gook to me too, so let’s jump into a code sample.



I’ve frequently written code like the following to iterate through an IDataReader and read the data.  There’s always a little bit of coercion on the raw data from the database when you move the data to .Net Types.  Several database engines don’t have a true boolean type, so you use a coding convention like “0/1″ or “Y/N” as a standin for a boolean type.  You may want to treat a null value in the database as either an empty string or 0.  That results in a lot of code like this below:


		public Somebody[] GetSomebodies()
{
ArrayList list = new ArrayList();

using (IDataReader reader = this.fetchReader())
{
while (reader.Read())
{
string name = reader.GetString(0);
int age = reader.IsDBNull(1) ? 0 : reader.GetInt32(1);
string email = reader.IsDBNull(2) ? string.Empty : reader.GetString(2);
bool active = reader.GetString(3) == “Y” ? true : false;

Somebody somebody = new Somebody(name, age, email, active);
list.Add(somebody);
}
}

return (Somebody[]) list.ToArray(typeof (Somebody));
}


 


Over time this kind of coercion code builds up, and it’s all a bunch of duplicated code.  It’s also irritating when you hit defects because you forgot to check for null values on a column.  Not to mention that it makes the code harder to read because you’re getting tangled up in the casting.  Wouldn’t be nice if the DataReader could be smart enough to do the type coercion and null substitution for us?  We can’t very easily go and alter SqlClient or OracleClient to do this ourselves (they’re both sealed).  One slick alternative I’ve seen is to use the Decorator pattern to create a new IDataReader class that wraps the underlying reader just to intercept the null values and substitute a default value.  Here’s what the code might look like with the decorated reader.


 

		public Somebody[] GetSomebodies()
{
ArrayList list = new ArrayList();

using (IDataReader innerReader = this.fetchReader())
{
IDataReader reader = new DefaultedReader(innerReader);

while (reader.Read())
{
string name = reader.GetString(0);
int age = reader.GetInt32(1);
string email = reader.GetString(2);
bool active = reader.GetBoolean(3);

Somebody somebody = new Somebody(name, age, email, active);
list.Add(somebody);
}
}

return (Somebody[]) list.ToArray(typeof (Somebody));
}


 


All I did is push a lot of the coercion code to the new decorator class.  It’s not that big of deal, but it frees me to concentrate on the mapping rather than a bunch of defensive coding.  A partial implementation of the DefaultedReader is below.

	public class DefaultedReader : IDataReader
{
private readonly IDataReader _innerReader;

public DefaultedReader(IDataReader innerReader)
{
_innerReader = innerReader;
}

public void Close()
{
_innerReader.Close();
}

// Straight Delegation
public bool Read()
{
return _innerReader.Read();
}

// Substitute true/false for “Y”/”N”
public bool GetBoolean(int i)
{
string booleanString = _innerReader.GetString(i);
return booleanString == “Y” ? true : false;
}

public string GetString(int i)
{
return _innerReader.IsDBNull(i) ? string.Empty : _innerReader.GetString(i);
}

// Wrap the call to _innerReader.GetInt32()
public int GetInt32(int i)
{
return _innerReader.IsDBNull(i) ? 0 : _innerReader.GetInt32(i);
}

// Rest of the IDataReader implementation
}


The mechanics are pretty simple.  The DefaultedReader class implements the IDataReader interface, so it can be used any place that expects an IDataReaderDefaultedReader takes an IDataReader as its only constructor argument and keeps an internal reference to the “inner” reader.  Most methods in the DefaultedReader will just delegate to the inner reader.  I haven’t been paying attention enough to know if the new Nullable types eliminate the need for this trick, but I just wanted to demonstrate how a construct like this could be useful.


A lot of the elegance of the decorator pattern is the ability to add extra behavior to a class without creating subclasses.  We’ve already decided that we can’t effectively make a subclass of SqlDataReader just to do the null value resolution.  Using a decorator in a case like this eliminates the need to create lots of subclass’s.  Our DefaultedReader class will work identically when it’s decorating a SqlDataReader as it will an OracleDataReader, OleDbDataReader, or OdbcDataReader.


Here’s another example.  In my StructureMap code I have an interface called IInstanceFactory that is responsible for the assembly of a named object instance.  The basic InstanceFactory class reads configuration and creates a new instance based on that configuration.  Here’s part of that interface.

	/// 
/// Interface for a “Factory” pattern class that creates object instances of the PluginType
///

public interface IInstanceFactory
{
///
/// Creates an object instance for the InstanceKey
///

/// The named instance
///
object GetInstance(string InstanceKey);

///


/// Creates a new object instance of the default instance memento
///

///
object GetInstance();
}

Sometimes you aren’t going to want a brand new instance every time.  You may want to share the same instance for every request.  You might want to associate an instance with the executing thread or the current HttpContext.  StructureMap has a simple mechanism to modify the creation of new object instances by wrapping one or more decorators around an InstanceFactory.  The calling code in StructureMap only cares about the IInstanceFactory interface, so calling into the decorator(s) is transparent to the calling code.  So far, the only thing I’ve used this for is to create pseudo-Singleton instances.  The entire code for the decorator class is below.

	/// 
/// The SingletonInterceptor is a GoF Decorator around an IInstanceFactory that ensures that
/// only one instance is created for a given InstanceKey as a more testable alternative to
/// the GoF Singleton pattern.
///

[Pluggable(“Singleton”)]
public class SingletonInterceptor : InstanceFactoryInterceptor
{
private Hashtable _instances;

public SingletonInterceptor() : base()
{
_instances = new Hashtable();
}

public override object GetInstance(string instanceKey)
{
ensureInstanceIsCached(instanceKey);

return _instances[instanceKey];
}

private void ensureInstanceIsCached(string instanceKey)
{
if (!_instances.ContainsKey(instanceKey))
{
lock (this)
{
if (!_instances.ContainsKey(instanceKey))
{

						// Delegate to teh inner InstanceFactory to construct a new instance
object instance = this.InnerInstanceFactory.GetInstance(instanceKey);
_instances.Add(instanceKey, instance);
}
}
}
}

public override object GetInstance()
{
return this.GetInstance(this.DefaultInstanceKey);
}
}


Most of the work is still delegated to the inner IInstanceFactory.  Some of the other possibilities would be adding caching or object pooling, providing an opportunity to attach a decorator to the new instance, or substituting a mock object or a stub during testing (this has turned out to be pretty effective in some cases).


Examples in the .Net Framework


One of the reasons I think design patterns are important is that they occur in other people’s code we inherit and use.  Recognizing the patterns in someone else’s code can help you understand that code.  Here’s a handful of examples from the



  • Chaining IHttpModule classes in an ASP.NET application is an example of a decorator.  Each IHttpModule in the interception chain adds behavior before it delegates to it’s inner IHttpModule.  Microsoft refers to this specific usage or a decorator as an Intercepting Filter.
  • The XmlValidatingReader class adds schema validation to any type of XmlReader.  Clients that depend on the XmlReader type never know the difference.
  • The System.IO.BufferedStream decorates any other kind of Stream to add buffering.  By using a decorator pattern, the .Net team didn’t need to create specific subclasses for “BufferedFileStream” or “BufferedMemoryStream.”  There is another Stream class that decorates other streams to provide transparent encryption.

Wrapping Up


The decorator pattern can help decompose optional or extra behavior into a separate class.  Any chance you get to eliminate structured logic “if/then” constructs is a chance to improve the readability and maintainability of the code.  The decorator also gives you a relatively low risk way to extend a system with new behavior like security, caching, or extra instrumentation at configuration time via the Open/Closed Principle.


If this was useful, or I could have done something better to explain the pattern, let me know.  I’ll try to do a couple more of these posts over the next month.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Design Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://flimflan.com/blog Joshua Flanagan

    The IDataReader example of Decorator is a good one, I’ll have to remember that.

    I don’t agree with the IHttpModule example, however. IHttpModules do not wrap other IHttpModules. It is just a defined interface (Init and Disopse) the runtime uses so that the modules can register/unregister themselves to application events. If I create a new module, it is not called by other modules, and does not call other modules.

    The implementation seems closer to the Observer pattern to me.

  • Michael

    Clint, an excellent point. While I think we should strive toward the “interalize it” mentality in production code, there’s the question of how to actually do so. For me, like you, it means writing code with the pattern, which in turn means finding a use for the pattern. So while it’s not good to try to force fit a laundry list of patterns into a design, there’s still a time and place for trying to do so, and the initial learning process is definitely among them.

  • Clint

    I get what you are saying Michael. For me, actually implementing the pattern helps me understand it better so often I try to force myself to use it somewhere so I don’t “forget it”. It is easy to see an example in a book and think I understand it. Then I get a chance to implement it and then I really understand it and what I “thought” I knew before wasn’t quite right. Not the best strategy but when you’re in college and the projects are usually small it is hard to use patterns.

    Most of the references I have seen also mention IO streams from Java and .Net. The Head First Design Patterns book shows a nice non streaming use of Decorator though. For some patterns I’ve found that I’ve already used them without knowing they were a pattern. Some of them just naturally happen with good OO design.

  • jmiller

    I’m going to have to remember the “concealed weapon” analogy.

  • Michael

    Clint spawned a thought in my head regarding usage of patterns, specifically in reference to “Today I was just looking at Decorator and was thinking that man, there must be somewhere that I can use this.” I do that as well, and I think it’s the wrong way to approach the study of patterns.

    When you first obtain a license to carry a concealed weapon, you don’t run out an try to find a target amongst your neighbors. It becomes an option that’s available to you should a situation occur that justifies it’s usage (perhaps that sounds a little callous, but it’s just an example).

    A similar thing happens with patters. The point is to understand and internalize the advantages and disadvantages of each pattern, along with where they came from and how they interact, so that when you’re trying to pull data from an IDataReader, you immediately recognize the usefullness of Decorator.

    I just took Clint’s quote as an example, and meant no offense to anyone. I just wanted to mention that you shouldn’t just try to use patterns straight out of the books, but instead try to internalize them. Usage will naturally follow as you work with your designs and write code.

    And read posts like this 😉 I always see references to Streams when reading about Decorator, and it leads to a limited understanding. You’ve given us concrete examples from a wider array of uses, and that helps tremendously.

  • Clint

    Woah, I’m doing datareader code like that right now, almost identical to yours. I’ve been reading Head First Design Patterns and Holub on Patterns this week. Today I was just looking at Decorator and was thinking that man, there must be somewhere that I can use this. I didn’t even think of it this way though. Great idea. Thanks.