Wednesday, February 9, 2011

Decorator Pattern


Decorator Pattern 
In Design Patterns, the authors define the Decorator pattern as:

Attach additional responsibilities to an object dynamically.

Decorators provide a flexible alternative to subclassing for extending functionality.

In the Decorator pattern, a decorator object is wrapped around the original object. This is typically achieved having the original object as a member of the decorator, with the decorator forwarding the requests to the original object and also implementing the new functionality.

Usage Scenarios
  • Add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects.
  • Be able to withdraw responsibilities
    For example: The java.util.Collections.unmodifiableCollection(Collection) removies the ability to change a given collection by wrapping it with a decorator that throws an UnSupportedException when you try to modify the Collection.
  • When extension by subclassing is impractical, such as when a large number of independent extensions produce an explosion of subclasses to support every combination. Or a class is unavailable for subclassing.
Design
Here is the UML diagram of the Decorator pattern followed by a description of the various involved components.
  • Component: Defines the interface for objects that can have responsibilities added to them dynamically.
  • ConcreteComponent: Defines an object to which additional responsibilities can be attached.
  • Decorator: Maintains a reference to a Component object and defines an interface that conforms to Component's interface.
  • ConcreteDecorator: Adds responsibilities to the component.
Implementing Decorator Pattern
The following is sample implementation of the Decorator pattern in Java.
  1. The Component Interface
interface Breakfast {
   public double cost();
   public String getDescription();
}
Component.java
  1. The Concrete Component
public class Dosa implements Breakfast{
 
  public double cost() {
         return 15.0;
  }
  public String getDescription() {
         return "Dosa";
  }
}
Dosa Rs: 15



public class Idli implements Breakfast {

  public double cost() {
         return 10.50;
  }

  public String getDescription() {
         return "Idly";
  }
}
Idli Rs: 10.50

ConcreteComponent.java
  1. The Decorator
public interface Decorator extends Breakfast {

  public void addedBehavior();

}
Decorator.java
Note: The decorator interface has to conform to the component interface, hence it extends Component.

  1. The Concrete Decorator
public class MasalaDecorator implements Decorator {
  Breakfast breakfast;

  public MasalaDecorator(Breakfast breakfast) {
         this.breakfast = breakfast;
  }

  public String getDescription() {
         return breakfast.getDescription() + "with Masala Decoration";
  }

  public double cost() {
         return breakfast.cost() + 5.50;
  }

  public void addedBehavior() {
         System.out.println("Do additional stuff");
  }
}
Masala Decoration Rs: 5.50


public class OnionDecorator implements Decorator {
  Breakfast breakfast;

  public OnionDecorator(Breakfast breakfast) {
         this.breakfast = breakfast;
  }

  public String getDescription() {
         return breakfast.getDescription() + " with Onion Decoration";
  }

  public double cost() {
         return breakfast.cost() + 3.50;
  }

  public void addedBehavior() {
         System.out.println("Do additional stuff");
  }
}
Onion Decortion Rs: 3.50

ConcreteDecorator.java


  1. The Client: Feeling Hungry!!! Time for Breakfast

public class BreakfastMenu {

  public static void main(String[] args) {

         // without adding decorators
         Breakfast menu1 = new Dosa();
         System.out.println(menu1.getDescription() + " Rs. " +       menu1.cost());

         Breakfast menu2 = new Idli();
         System.out.println(menu2.getDescription() + " Rs. " + menu2.cost());

         // adding decorators to Dosa
         Breakfast menu3 = new MasalaDecorator(new Dosa());
         System.out.println(menu3.getDescription() + " Rs. " + menu3.cost());
Dosa with Masala Decoration Rs: 20.50


         Breakfast menu4 = new OnionDecorator(new Dosa());
         System.out.println(menu4.getDescription() + " Rs. " + menu4.cost());
Dosa with Onion Decoration Rs: 18.50

         Breakfast menu5 = new MasalaDecorator(new OnionDecorator(new Dosa()));
         System.out.println(menu5.getDescription() + " Rs. " + menu5.cost());
Dosa with Masala and Onion Decoration Rs: 24 


         // adding decorators to Idli
         Breakfast menu6 = new MasalaDecorator(new Idli());
         System.out.println(menu6.getDescription() + " Rs. " + menu6.cost());
Idli with Masala Decoration Rs: 16


         Breakfast menu7 = new OnionDecorator(new Idli());
         System.out.println(menu7.getDescription() + " Rs. " + menu7.cost());
Idli with Onion Decoration Rs: 14

         Breakfast menu8 = new MasalaDecorator(new OnionDecorator(new Idli()));
         System.out.println(menu8.getDescription() + " Rs. " + menu8.cost());
Idli with Masala and Onion Decoration  Rs: 19.5

  }
}
Client.java



Rates for the breakfast we ordered
Dosa Rs. 15.0
Idly Rs. 10.5
Dosa with Masala Decoration Rs. 20.5
Dosa with Onion Decoration Rs. 18.5
Dosa with Onion Decoration with Masala Decoration Rs. 24.0
Idly with Masala Decoration Rs. 16.0
Idly with Onion Decoration Rs. 14.0
Idly with Onion Decoration with Masala Decoration Rs. 19.5    
 

Highlights of Decorator Pattern 

·         You can wrap a component with any number of decorators.
·         The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job.
·         Objects can be decorated at any time, so we can decorate objects dynamically at runtime with as many decorators as we like.
·         Decorators can extend the state of the component.
·         Decorators can add new methods. however new behavior is typically added by doing computation before or after an existing method in the component.
·         In our designs we should allow behavior to be extended without the need to modify existing code.
·         Composition and delegation can often be used to add new behaviors at runtime.
·         The Decorator Pattern provides an alternative to sub classing for extending behavior.
·         Decorator classes mirror the type of the components they decorate. (In fact, they are the same type as the components they decorate, either through inheritance or interface implementation.)
·         Decorators change the behavior of their components by adding new functionality before and/or after (or even in place of) method calls to the component.
·         Decorator is designed to let you add responsibilities to objects without sub classing.
·         Decorator lets us change the skin of an object. Strategy lets us change the guts.[GoF, p184]

Disadvantage : 
Only disadvantage is code maintenance can be a problem as it provides the system with a lot of similar looking small objects(each decorator). Decorators can result in many small objects in our design, and overuse can be complex.

Monday, February 7, 2011

Overloading Vs Overriding



OVERLOADING



Invoking Overloaded Methods 
Any Class can have more than one methods with the same name but with different argument lists, which means the method is overloaded.
Deciding which of the matching methods to invoke is based on the arguments. If you invoke the method with a String argument, the overloaded version that takes a String is called. If you invoke a method of the same name but pass it a float, the overloaded version that takes a float will run.
If you invoke the method of the same name but pass it a Foo object, and there isn't an overloaded version that takes a Foo, then the compiler will complain that it can't find a match.
  class Adder {
            public int addThem(int x, int y) {
                  return x + y;
            }

            // Overload the addThem method to add doubles instead of ints
            public double addThem(double x, double y) {
                  return x + y;
            }
      }

      // From another class, invoke the addThem() method
public class TestAdder {

      public static void main(String[] args) {
            Adder a = new Adder();

            int b = 27;
            int c = 3;
            int result = a.addThem(b, c); // Which addThem is invoked?
            double doubleResult = a.addThem(22.5, 9.3);

            }


The following are examples of invoking overloaded methods:
In the preceding TestAdder code, the first call to a.addThem(b,c) passes two ints to the method, so the first version of addThem()—the overloaded version that takes two int arguments—is called.
The second call to a.addThem(22.5, 9.3) passes two doubles to the method, so the second version of addThem()—the overloaded version that takes two double arguments—is called.

Important Funda:

Invoking overloaded methods that take object references rather than primitives is a little more interesting.
Say you have an overloaded method such that one version takes an Animal and one takes a Horse (subclass of Animal).
If you pass a Horse object in the method invocation, you'll invoke the overloaded version that takes a Horse. Or so it looks at first glance:




      class Animal {
      }

      class Horse extends Animal {
      }

      class UseAnimals {
            public void doStuff(Animal a) {
                  System.out.println("In the Animal version");
            }
            public void doStuff(Horse h) {
                  System.out.println("In the Horse version");
            }

            public static void main(String[] args) {
                  UseAnimals ua = new UseAnimals();
                  Animal animalObj = new Animal();
                  Horse horseObj = new Horse();
                  ua.doStuff(animalObj);
                  ua.doStuff(horseObj);
            }
      }


The output is what you expect:
In the Animal version
In the Horse version
But what if you use an Animal reference to a Horse object?
Animal animalRefToHorse = new Horse();
ua.doStuff(animalRefToHorse);
 Which of the overloaded versions is invoked?
You might want to say, "The one that takes a Horse, since It's a Horse object at runtime that's being passed to the method." But that's not how it works.
The preceding code would actually print: In the Animal version
Even though the actual object at runtime is a Horse and not an Animal, the choice of which overloaded method to call (in other words, the signature of the (method) is NOT dynamically decided at runtime).
To summarize, which overridden version of the method to call is decided at runtime based on object type, but which overloaded version of the method to call is based on the reference type of the argument passed at compile time.
If you invoke a method passing it an Animal reference to a Horse object, the compiler knows only about the Animal, so it chooses the overloaded version of the method that takes an Animal. It does not matter that at runtime there's actually a Horse being passed.


OVERRIDING


Polymorphism in Overloaded and Overridden Methods


How does polymorphism work with overloaded methods? From what we just looked at, it doesn't appear that polymorphism matters when a method is overloaded.

If you pass an Animal reference, the overloaded method that takes an Animal will be invoked, even if the actual object passed is a Horse.

Once the Horse masquerading as Animal gets in to the method, however, the Horse object is still a Horse despite being passed into a method expecting an Animal.

So it's true that polymorphism doesn't determine which overloaded version is called; polymorphism does come into play when the decision is about which overridden version of a method is called.

But sometimes, a method is both overloaded and overridden. Imagine the Animal and Horse classes look like this:

     public class Animal {
            public void eat() {
                  System.out.println("Generic Animal Eating Generically");
            }
      }

      public class Horse extends Animal {
            public void eat() {
                  System.out.println("Horse eating hay ");
            }

            public void eat(String s) {
                  System.out.println("Horse eating " + s);
            }
      }


Notice that the Horse class has both overloaded and overridden the eat() method.

Table shows which version of the three eat() methods will run depending on how they are invoked.


Method Invocation Code
Result
Animal a = new Animal();
a.eat();
Generic Animal Eating Generically
Horse h = new Horse();
h.eat();
Horse eating hay
Animal ah = new Horse();
ah.eat();
Horse eating hay Polymorphism works—the actual object type (Horse), not the reference type (Animal), is used to determine which eat() is called.
Horse he = new Horse();
he.eat("Apples");
Horse eating Apples
The overloaded eat (String s) method is invoked.
Animal a2 = new Animal();
a2.eat("treats");
Compiler error! Compiler sees that Animal class doesn't have an eat() method that takes a String.
Animal ah2 = new Horse();
ah2.eat("Carrots");
Compiler error! Compiler still looks only at the reference, and sees that Animal doesn’t have an eat() method that takes a String. Compiler doesn’t care that the actual object might be a Horse at
runtime.