Skip to content
October 1, 2008 / Shrikant Patil

Structural Design pattern: Decorator Design Pattern

I have started with Structural Design pattern; at first place I saw the name Decorator Pattern. As I read the name, I thought name itself describing the pattern, and I was right. The Structural Design Patterns uses classes and object to build complex structures. In this post I am going to share the first member of the Structural Design Patterns group, which is Decorator Design Pattern.
As per theoretical definition the decorator is defined as follows;
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub classing for extending functionality”.
We can add functionality to an object extending that class at compile time. But what if we are not sure until run time which functionality needs to be added for an object? The answer comes with the name of Decorator Pattern. Decorator is an object which warps an object which needs to be added with new functionality at run time.
Let us dig into deeply; The Decorator Pattern includes some of specific classes / Objects which are defined with a specific meaning.

  • Component: An Abstract Class which defines an interface for the objects which are get decorated with new functionality at run time. This class may define some specific implementations which are later get overridden by the subclasses to extend the functionality.
  • Concrete Component: This class derived Abstract Component Class, and it defines an object to which new functionality will be get added at run time
  • Decorator: This class derived from Abstract Component Class and holds a reference of Component object. It provides an interface for concrete Decorator objects.
  • Concrete Decorator: This class derived form Decorator class. It defines the implementation of functionality, which we want to add to a component at run time. This Object is used as a wrapper with new functionality, which warps around any of concrete component to add defined functionality at run time.

Here is the diagram of the pattern:
Let us work on coding an application. The application is an Computer shop. There are two types of models are available 1) Laptop and 2) Table Computer. Client can selected any model. After choosing the model of the computer client can choose the additional accessories 1) Head Phones and 2) DVD Writer.
In this application the Models Laptop and Table Computers are Concrete Components which are get warped by the concrete decorators depending on the addition accessories selection. i.e Head Phone or DVD Writer. When client choose additional accessories it means application need to add new functionality to the selected model. So let is start coding the application;

Creating Abstract Component:
At first we need to create a Abstract component;


package flexScript
{
    //Abstract Component Class
    //defines an interfece for both concrete component
    //and for Decorator.
    public class ComputerOrder
    {
        internal var description:String;
        internal var billingPrice:Number;
        public function getDescription():String
        {
            return description;
        }
        public function getBillingPrice():Number{
            return billingPrice;
        }
    }
}

As we can see, the abstract component class only defines an interface for both Decorator and Concrete Components.

Creating Concrete Components:
Concrete components are derived form Abstract Component (ComputerOrder) class. The class can define its own values for the properties and methods defined in the Abstract Component. Concrete Component are the object which are get warped by concrete Decorators to add functionality dynamically. Here we have to create two concrete Component Classes.
In our application The computer models Laptop and Table Computer acts as Concrete Components.
Both class define the own description and override the getBillingPrice() method to implement their specific price values.


package flexScript
{
    //concrete component class
    //derived form Abstract Component (computerOrder)
    public class LapTopOrder extends ComputerOrder
    {
        public function LapTopOrder()
        {
            //define description(inherited property from super class
            description = "LapTop Order:Processing..";
        }
        //overriding method which is defined
        //in Abstract Component(ComputerOrder) to implement
        //LapTop price
        override public function getBillingPrice():Number{
            return 40500;
        }

    }
}


package flexScript
{
    //concrete component class
    //derived form Abstract Component (computerOrder)
    public class TableComputer extends ComputerOrder
    {
        public function TableComputer()
        {
            //define description(inherited property from super class
            description = "Table Computer Order: Processing..";
        }
        //overriding method which is defined
        //in Abstract Component(ComputerOrder) to implement
        //Table Computer price
        override public function getBillingPrice():Number{
            return 23540;
        }

    }
}

Creating Decorator:
Decorator is an interface for concrete decorators, which adds functionality to the concrete components at run time. Decorator class is derived from the Abstract Component (computerOrder) class. So here is our Decorator interface class.


package flexScript
{
    //Decorator class derived form Abstract Component(ComputerOrder)
    public class OrderDecorator extends ComputerOrder
    {
        override public function getDescription():String{
            return description;
        }

    }
}


Creating Concrete Decorators:

These classes are derived from the Decorator (OrderDecorator), which defines the new functionality for a concrete component. Concrete Decorators are get warps the concrete component objects to add new functionality at run time. The concrete decorator holds a reference of Abstract Component object. The constructor of the class accept a parameter of the type of Abstract Component.
In our application after selecting the model of the computer, user selects the accessories like Head Phones or DVD writer. The both accessories are concrete decorator objects.
So The classes overrides both getDescription() and getBillingPrice() method to add new functionality description and price. Let us create both concrete decorator objects of our application.


package flexScript
{
    //concrete decorator class derived form decorator
    public class HeadPhone extends OrderDecorator
    {
        //Holds a reference of Component(ComputerOrder) object
        internal var order:ComputerOrder;
        //constructor should accept Component object
        public function HeadPhone(order:ComputerOrder)
        {
            this.order = order;
        }

        //override inherited methods to specific implementations
        override public function getDescription():String{
            return order.getDescription()+"\n- Head Phones";
        }
        override public function getBillingPrice():Number{
            return order.getBillingPrice()+ 300;
        }

    }
}


package flexScript
{
    //concrete decorator class derived form decorator
    public class DVDWriter extends OrderDecorator
    {
        //Holds a reference of Component(ComputerOrder) object
        internal var order:ComputerOrder;
        //constructor should accept Component object
        public function DVDWriter(order:ComputerOrder)
        {
            this.order = order;
        }
        //override inherited methods to specific implementations
        override public function getDescription():String{
            return order.getDescription()+"\n- DVD Writer";
        }
        override public function getBillingPrice():Number{
            return order.getBillingPrice()+ 2340;
        }

    }
}

Creating Client:
Our client is Flex mxml script file. The client displays list of available computer models (LapTop, Table Computer). After selecting a model user can selected additional accessories like HeadPhone and DVD Writer. Once selection is done user can click on submit Order. The Text area display the description and billing price information.
The code behind, when client click on submit order, it checks the model selected and create a new concrete component of selected model type. After that it checks for selected additional accessories and create a new concrete decorator warping the relating concrete component.
Here is the code of client;


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute">
<mx:Script>
    <!&#91;CDATA&#91;
        import flexScript.DVDWriter;
        import flexScript.HeadPhone;
        import flexScript.TableComputer;
        import flexScript.LapTopOrder;
        import flexScript.ComputerOrder;

        private var order:ComputerOrder;
        private var modelsList:Array = new Array("LapTop","TableComputer"); 

        private function processOrder():void{
            checkModels();
            checkOptions();
            if(order == null){
                return;
            }else{
                tracer.text = order.getDescription()+"\nBill Price:"+order.getBillingPrice()+"\n";
            }
        }

        private function checkModels():void{
            var modelSelected:String = models.selection.label;
            switch(modelSelected){
                case "LapTop": order = new LapTopOrder();
                                break;
                case "TableComputer": order = new TableComputer();
                                break
            }
        }
        private function checkOptions():void{
            if(opt1.selected) {order = new HeadPhone(order);}
            if(opt2.selected) {order = new DVDWriter(order);}
        }
    &#93;&#93;>
</mx:Script>
<mx:HBox x="347" y="84">
    <mx:VBox>
        <mx:Text text="Select Model"/>
        <mx:RadioButtonGroup id="models"/>
        <mx:RadioButton groupName="models" label="LapTop" selected="true"/>
        <mx:RadioButton groupName="models" label="TableComputer"/>
    </mx:VBox>
    <mx:VBox>
        <mx:Text text="select Options"/>
        <mx:CheckBox label="Head Phones" id="opt1" selected="true"/>
        <mx:CheckBox label="DVD Writer" id="opt2"/>
    </mx:VBox>
</mx:HBox>
    <mx:Button x="423" y="166" label="Button" click="processOrder()"/>
    <mx:TextArea x="347" y="212" width="218" height="105" id="tracer"/>
</mx:Application>

For further, if we want to add more computer model and more accessories we just need to create more concrete component class and concrete decorator, without making any changes in exiting code. Its pretty useful. Here is a sample screenshot of the application;

Advertisements

2 Comments

Leave a Comment
  1. Alexander Arendar / Oct 2 2008 11:20 am

    Hey dude,

    very nice blog.
    I am only starting learning flex but will add a link to your blog to my one in order to keep it under my hand. Will read it soon.

  2. Computer Shop / Jun 23 2009 5:45 am

    Thank you for your post

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: