Friday 25 November 2016

Design Patters : Tutorial 1

These can be majorly divided into three types:

  1. Creational Pattern : These patten create a way hiding the creation logic.
               1. Singleton
               2. FactoryPattern


  1. Structural Pattern : These patterns are concerned with class and object composition. The Composition of these gives an added functionality.
    1. Decorator                                                     
    2. Adapter
    3. Facade
    4. Composite 
  2. Behavioural Pattern : These patterns are concerned with communication between objects.
    1. Template
    2. Visitor
    3. Observer 
Decorator Design Pattern

Usecase : Suppose Star Bucks has various Beverages and it want to charge various customers with different toppings and for this we can use the decorator pattern.

public  abstract class Beverage {

       String description = "Unknown Beverage";

       public String getDescription() {
              return description;
       }

       public abstract double cost();
}

public class Expresso extends Beverage{

       public Expresso(){
              description = "Expresso";
       }

       @Override
       public double cost() {
              System.out.println("Inside Expresso Cost");
              return 1.99;
       }
}

public abstract class CondimentDecorator extends Beverage{

       public abstract String getDescription();
}

public class Mocha extends CondimentDecorator{

       Beverage beverage;

       public Mocha(Beverage beverage){
              this.beverage = beverage;
       }

       public String getDescription(){
              System.out.println("Inside Mocha Description");
              return beverage.getDescription() + " , Mocha ";
       }

       public double cost() {
              System.out.println("Inside Mocha Cost");
              return beverage.cost() + .20;
       }
}

public class Soy extends CondimentDecorator{

       Beverage beverage;

       public Soy(Beverage beverage){
              this.beverage = beverage;
       }

       public String getDescription(){
              System.out.println("Inside Soy Description");
              return beverage.getDescription() + " , Soy ";
       }

       public double cost() {
              System.out.println("Inside Soy Cost");
              return beverage.cost() + .40;
       }
}

public class StarbuzzCoffee {

       public static void main(String[] args) {
              Beverage beverage = new Expresso();
              beverage =  new Mocha(beverage);
              beverage =  new Soy(beverage);

              System.out.println("Description : "+beverage.getDescription()
              +" Cost : "+ beverage.cost());
       }

}

Output of this is:

Inside Soy Description
Inside Mocha Description
Inside Soy Cost
Inside Mocha Cost
Inside Expresso Cost
Description : Expresso , Mocha  , Soy  Cost : 2.59

In this we are adding Mocha and Soy to the Expresso Beverage and hence we override these methods and in the main we call the objects as shown.

RealWorldExample: Java IO Classes.


Facade Design Pattern

The Facade design pattern hides the internal implementation and provides an interface to the user to execute the commands. The example to link to a real world is suppose you want to Watch a movie in your home theatre. Before doing that you need to turn on the popcorn popper,dim the lights, put the screen down etc. For you to remember all these tasks is a challenge and in order to solve this, the Facade design pattern gives the interface which internally handles all these tasks. So lets take an code example of this.

public interface Shape {
       void draw();
}

public class Circle implements Shape {

       public void draw(){
              System.out.println("Rectangle : draw");
       }
}

public class Rectangle implements Shape {

       public void draw(){
              System.out.println("Rectangle : draw");
       }
}

public class Square implements Shape {

       public void draw(){
              System.out.println("Square : draw");
       }
}

public class ShapeMaker {

       private Shape circle;
       private Shape rectangle;
       private Shape square;

       public ShapeMaker(){
              this.circle = new Circle();
              this.rectangle = new Rectangle();
              this.square = new Square();
       }

       public void drawCircle(){
              circle.draw();
       }

       public void drawRectangle(){
              rectangle.draw();
       }

       public void drawSquare(){
              square.draw();
       }
}

public class FacadePatternDemo {

       public static void main(String[] args) {
              ShapeMaker shapeMaker = new ShapeMaker();
              shapeMaker.drawCircle();
              shapeMaker.drawRectangle();
              shapeMaker.drawSquare();
       }
}

Adapter Design Pattern

The best example of a adapter design pattern is that an adapter which is used between the port and the plug.

public interface Duck {

       void quack();
       void fly();
}

public class MallardDuck implements Duck {

       @Override
       public void quack() {
              System.out.println("Quack");

       }

       @Override
       public void fly() {
              System.out.println("I'm flying");

       }
}

public interface Turkey {

       public void gobble();
       public void fly();

}

public class WildTurkey implements Turkey {

       @Override
       public void gobble() {
              System.out.println("Gobble Gobble");
       }

       @Override
       public void fly() {
              System.out.println("I'm flying a short distance");
       }
}

public class TurkeyAdapter implements Duck {

       Turkey turkey;

       public TurkeyAdapter(Turkey turkey){
              this.turkey = turkey;
       }

       @Override
       public void quack() {
              turkey.gobble();
       }

       @Override
       public void fly() {
              for(int i = 0 ; i < 5;i++){
                     turkey.fly();
              }
       }

}

public class DuckTestDrive {

       public static void main(String[] args) {
              MallardDuck duck = new MallardDuck();
              WildTurkey turkey = new WildTurkey();

              Duck turkeyAdapter = new TurkeyAdapter(turkey);
              System.out.println("The Turkey says...");

              turkey.gobble();
              turkey.fly();

              System.out.println("The Duck Says");
              duck.quack();
              duck.fly();

              System.out.println("The TurkeyAdapter says");
              turkeyAdapter.quack();
              turkeyAdapter.fly();
       }
}

Output is:

The Turkey says...
Gobble Gobble
I'm flying a short distance
The Duck Says
Quack
I'm flying
The TurkeyAdapter says
Gobble Gobble
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance

Template Design Pattern

This designs the skeleton of the algorithms.Some of the methods are implemented by the class and the rest are overridden by the subclass.

public abstract class CaffeineBeverage {

       final void prepareReceipe() {
              boilWater();
              brew();
              pourInCup();
              addCondiments();
       }

       abstract void brew();
       abstract void addCondiments();

       void boilWater(){
              System.out.println("Boiling Water");
       }

       void pourInCup(){
              System.out.println("Pouring into cup");
       }
}

public class Coffee extends CaffeineBeverage {

       @Override
       void brew() {
              System.out.println("Dripping Coffee through Filter");
       }

       @Override
       void addCondiments() {
              System.out.println("Adding Sugar and Milk");
       }
}

public class Tea extends CaffeineBeverage{

       public void brew(){
              System.out.println("Steeping the tea");
       }

       public void addCondiments(){
              System.out.println("Adding Lemon");
       }

}

No comments:

Post a Comment