Click here to Skip to main content
15,885,278 members
Articles / Programming Languages / C#

Deep Inside Structural Patterns :: Decorator Pattern :: Part 2

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
20 May 2014CPOL6 min read 10.7K   14   2
We have discussed in our previous post the decorator pattern’s role, and giving a very detailed illustration about it. Also, we have discussed its design varieties and clarified when to use each design and why.

Introduction

We have discussed in our previous article the decorator pattern’s role, and given a very detailed illustration about it. Also, we have discussed its design varieties and clarified when to use each design and why.

Today, we will complete our discussion about decorator pattern. We will talk deeply about different examples from the real world cases to give you a deeper understanding of this pattern. Also, we will discuss when to use this pattern in real world situations.

We will demonstrate first a simple example and then move on to more complicated ones and more variations.

1. Example: Use Case Diagram Tool

Use case diagram is one of the fundamental diagrams of the unified modeling language (UML). We use the use case diagrams to describe all the use cases a user can interact with within an application.

Here, we will start to build a simple (Really, it is a very simple, just for demonstrations purposes) use case diagram tool.

If we look more thoughtfully into the available shapes that can be drawn in a use case diagram, we will find them to be 3 main shapes:

  1. Actors
  2. Use cases
  3. Arrows (which represent relationships between actors, or between use cases or between actors and use cases)

But a deeper look, we will find that each shape has a different look in different situations.

As described in the following diagram, some of the variations that could be applied to any shape during drawing process of use case diagrams:

Image 1

The challenge here is that we want to build an application that covers all the variations available and with an ability to add more shapes in future in case any updates happen to UML.

Here comes the magic of the decorator pattern. Let’s get started:

Analyzing the last diagram shows us that we have 3 main shapes with different variations. Variations means here decorators which can be applied to different shapes to show us the right final shape.

More analyzing, we are noticing that we have some kind of hybrid decorators like for example, dotted line with a tag. In fact, they are two decorators tag decorator and dotted line decorator.

Let’s first start with one shape and then we will elaborate on this.

IShape Interface and Actor Class

Image 2

IShape Interface

C#
public interface IShape
{ 
     Bitmap Draw();
}  

Actor Class

C#
public class Actor : IShape
{
     public Bitmap Draw()
     {
         Bitmap image = new Bitmap(200, 200);
 
         using (Graphics graphics = Graphics.FromImage(image))
         {
              using (Pen blackPen = new Pen(Brushes.Black))
              {
                   // Drawing head
                   graphics.DrawEllipse(blackPen, 100, 20, 20, 20);
 
                   // Drawing backbone
                   graphics.DrawLine(blackPen, 110, 40, 110, 80);
 
                   // Drawing arms
                   graphics.DrawLine(blackPen, 110, 55, 130, 55);
                   graphics.DrawLine(blackPen, 110, 55, 90, 55);
 
                  // Drawing legs
                  graphics.DrawLine(blackPen, 110, 80, 130, 100);
                  graphics.DrawLine(blackPen, 110, 80, 90, 100);
              }
         }
 
        return image;
    }
} 

If we try now to use this class with a Windows Forms application in .NET, for example, you will write just like the following code after dragging a picture box into the form:

C#
Actor actor = new Actor();
pictureBox1.Image = actor.Draw(); 

Run the project, you will see:

Image 3

Now we need to add some sugar, so let’s add a decorator called TagDecorator which will be responsible for adding tags (titles) to any shape.

Here is the class diagram (following the guidelines of decorator patterns):

TagDecorator Class

Image 4

C#
public class TagDecorator : IShape
{
     private IShape _shape;
     private string _tag;
 
     public TagDecorator(IShape shape, string tag)
     {
          _shape = shape;
          _tag = tag;
     }
 
     public Bitmap Draw()
     {
         // Getting the actor shape without tags
         Bitmap image = _shape.Draw();
 
         // Writing the tag under the actor shape
         using (Graphics grahpics = Graphics.FromImage(image))
         {
              grahpics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
              StringFormat stringFormat = new StringFormat
              {
                   Alignment = StringAlignment.Center,
                   LineAlignment = StringAlignment.Center
              };
              grahpics.DrawString(_tag, new Font("Times New Roman", 12), 
              Brushes.Black, new RectangleF(10, 110, 200, 20), stringFormat);
         }
 
         return image;
     }
} 

Let’s try to draw this decorated actor to the form. So we will write this code:

C#
Actor actor = new Actor();
TagDecorator actorTag = new TagDecorator(actor, "User");
pictureBox1.Image = actorTag.Draw(); 

And see the output:

Image 5

Now let’s make things more complicated, I will just give you the concepts and let you try to implement them.

What if we want to add more shapes, simply we will use the following diagram:

Image 6

What about more decorators?!

Image 7

Go, and try to build your own diagramming tool.

2. Real World Examples

Now we will demonstrate some real world examples may be we are using in a daily basis but we don’t know.

In a very good article by Rob Pierry, he discussed when a decorator pattern has been used within .NET. He said:

“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:

C#
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.

This ability to dynamically attach new functionality to objects transparently using composition is an example of the Decorator pattern”.

This is valid also for Java developers as well as far as I know in java.io namespace.

Let’s also demonstrate more general real examples:

Here are four ways the Decorator pattern is used in the real world (Excerpt from C# 3.0 Design patterns):

  • As our small example illustrated, the Decorator pattern fits well in the graphics world. It is equally at home with video and sound; for instance, video streaming can be compressed at different rates, and sound can be input to a simultaneous translation service.
  • At a more mundane level, decorators abound in the I/O APIs of C# as illustrated.
  • In today’s world of mobile devices, web browsers and other mobile applications thrive on the Decorator pattern. They can create display objects suitable for smaller screens that include scroll bars and exclude banners that would be standard on desktop display browsers, for example.
  • The Decorator pattern is so useful that there are now actual Decorator classes in .NET 3.0. The one in System.Windows.Controls “provides a base class for elements that apply effects onto or around a single child element, such as Border or Viewbox.”

3. When to Use?

When you have:

  • An existing component class that may be unavailable for subclassing

Or when you want to:

  • Attach additional state or behavior to an object dynamically
  • Make changes to some objects in a class without affecting others
  • Avoid subclassing because too many classes could result

4. Finally

At last, we have finished demonstrating this pattern and its details. Your feedback is welcome.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Egypt Egypt
Graduated at Ain-Shams University, Faculty of Engineering, Computers and Systems Department since 2006.

Experienced Software Engineer who is developing, training and leading development teams to build flexible, maintainable, and easy to use Internet/Intranet applications using latest technologies like C# .NET, ASP.NET, ASP.NET AJAX, MVC, jQuery, Umbraco, SQL Server and others.

My career objective is to provide quality solutions to complex business problems within scope using latest Microsoft technologies. Extensive experience in .NET programming, databases and technical communication. Flexible as regards moving from project to project and in assimilating new technologies.

Proven team leadership skills. And now looking to continue making a significant contribution within design and development / leading a technical team or consultancy role in my current position and the next ones.

Simply, I would like to be a .NET GURU.

My best achievement is to solve business problems to mankind using my programming skills which I am already doing like eating and drinking.

But the best one is when you save more than 200,000 EGP per month after deploying your software in an organization! That was in ISI when we save a lot of money, work and hassle after transforming very critical procedures processed by a very poor manual paper system to a very efficient paperless one just using a browser, a keyboard, and a cup of coffee!

Comments and Discussions

 
SuggestionPrevious article Pin
deebee++26-May-14 22:24
professionaldeebee++26-May-14 22:24 
GeneralRe: Previous article Pin
Ahmed Abdul Moniem27-May-14 21:31
professionalAhmed Abdul Moniem27-May-14 21:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.