CHAPTER 5

image

Decorator Patterns

GoF Definition: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

Concept

This main principle of this pattern says that we cannot modify existing functionalities but we can extend them. In other words, this pattern is open for extension but closed for modification. The core concept applies when we want to add some specific functionalities to some specific object instead of to the whole class.

Real-Life Example

Suppose you already own a house. Now you have decided to add an additional floor. Obviously, you do not want to change the architecture of ground floor (or existing floors). You may want to change the design of the architecture for the newly added floor without affecting the existing architecture for existing floor(s).

Computer World Example

Suppose in a GUI-based toolkit, we want to add some border properties. We can do this by inheritance. But it cannot be treated as the best solution because our user or client cannot have absolute control from the creation. The core of that choice is static there.

Decorator can offer us a more flexible approach: here we may surround the component in another object. The enclosing object is termed “decorator.” It conforms to the interface of the component it decorates. It forwards requests to the component. It can perform additional operations before or after those forwarding requests. An unlimited number of responsibilities can be added with this concept.

Illustration

Please go through this example. Here we have not tried to modify the original doJob() method’s functionality. Two decorators, ConcreteDecoratorEx_1 and ConcreteDecoratorEx_2, are added here to enhance functionality, but the original doJob()’s working is not disturbed due to this addition.

UML Class Diagram

9781484218013_unFig05-01.jpg

Package Explorer view

High-level structure of the parts of the program is as follows:

9781484218013_unFig05-02.jpg

Implementation

package decorator.pattern.demo;

abstract class Component
    {
        public abstract void doJob();

    }
    class ConcreteComponent extends Component
    {
        @Override
          public void doJob()
        {
                System.out.println(" I am from Concrete Component-I am closed for modification.");

                }
    }

    abstract class AbstractDecorator extends Component
    {
        protected Component com ;
        public void SetTheComponent(Component c)
        {
            com = c;
        }
        public void doJob()
        {
            if (com != null)
            {
                com.doJob();
            }
        }

    }
    class ConcreteDecoratorEx_1 extends AbstractDecorator
    {
       public void doJob()
        {
            super.doJob();
            //Add additional thing if necessary
            System.out.println("I am explicitly from Ex_1");
        }
    }
    class ConcreteDecoratorEx_2 extends AbstractDecorator
    {
        public  void doJob()
        {
                System.out.println(“”);
                System.out.println("***START Ex-2***");
            super.doJob();
            //Add additional thing if necessary
            System.out.println("Explicitly From DecoratorEx_2");
            System.out.println("***END. EX-2***");
        }
    }
    class DecoratorPatternEx
    {
        public static void main(String[] args)
        {
                System.out.println("***Decorator pattern Demo***");
            ConcreteComponent cc = new ConcreteComponent();

            ConcreteDecoratorEx_1 cd_1 = new ConcreteDecoratorEx_1();
            // Decorating ConcreteComponent Object //cc with ConcreteDecoratorEx_1
            cd_1.SetTheComponent(cc);
            cd_1.doJob();

            ConcreteDecoratorEx_2 cd_2= new ConcreteDecoratorEx_2();
            // Decorating ConcreteComponent Object //cc with ConcreteDecoratorEx_1 & //ConcreteDecoratorEX_2
            cd_2.SetTheComponent(cd_1);//Adding //results from cd_1 now
            cd_2.doJob();
        }
    }

Output

9781484218013_unFig05-03.jpg

Note

What are the main advantages of using decorator patterns?

  1. Without disturbing existing objects in the system, we can add new functionality to a particular object.
  2. We can code incrementally. For example, we’ll make a simple class first and then one by one we can add decorator objects to them as needed. As a result, we do not need to take care of each and every possible scenario in the beginning. On the other hand, we must acknowledge that making a complex class first and then extending its functionality is a much more complex procedure.

How is this pattern different from inheritance?

We can add or remove responsibilities by simply attaching or detaching decorators. But with the simple inheritance technique, we need to create a new class for new responsibilities. So, there will be many classes inside the system, which in turn can make the system complex.

What is the major disadvantage of using this pattern?

First of all, if we are careful enough, there is no significant disadvantage. But if we create too many decorators in the system, the system will be hard to maintain and debug. At the same time, the decorators can create unnecessary confusion.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.174.23