Wednesday, 30 October 2019

Decorator Pattern

Decorator Patten is a Structural Patter. i.e It talks about how to structure your classes.

Decorator pattern just decorates the pre-existing class. So that we do not have the change the class that we are trying to decorate.

interface Shape{
    public void draw();
}

abstract class ShapeDecorator implements Shape{
    protected Shape targetObject;
    public ShapeDecorator(Shape targetToDecorate){
         targetObject = targetToDecorate;
    }

   @Override
   public void onDraw(){
        targetObject.draw();
   }
}


So now we can have RedShapeDecorator or BlueShapeDecorator concrete classes which will override onDraw(), call super and do more stuff to it, to decorate.

class RedShapeDecorator extends ShapeDecorator{
    public RedShareDecorator(Share target){
       super(target);
   }

   @Override
   public void draw(){
       super.draw();
       target.setBorderColor("red");
   }
}

Client will use it like.


Shape shape = new Circle();
Shape  redDecor = new RedShapeDecorator(shape);
redDecor.draw();

Design patterns

Principles:

  • Code for interface and not for implementation
  • Prefer object composition over inheritence 

Types of Design Patterns

1. Creational Design Patterns

  • Singleton
  • Factory 
  • Abstract factory
  • Builder
  • prototype
2. Structural Design Pattern
  • Adapter
  • Composite
  • Proxy
  • Fly weight
  • Facade
  • Bridge
  • Decorator 
3. Behavioral Design Patterns
  • Template method
  • Mediator
  • Chain of responsibility
  • Observer
  • Strategy
  • Command
  • State
  • Visitor
  • Iterator
  • Interpreter
  • memento

Prototype Design Pattern

Question: What is a prototype object creational pattern? 
Answer: You simple store a map of String & Object. And whenever you need an Object of a particular type(specified by string key), you simply make the copy of the prototype object your have stored earlier while creating the registry. 

Components:

1. Prototype registry: In this class you create a Map<String,Object> of Key and Prototype Object. and you ask this registry to give an object via a public api. When the api is called, it simply calls copies the prototype object. Simple way is to just call clone() method of java to deep copy. All objects in this pattern must be implementing Cloneable interface. 

2. Client: Asks the registry to get the object.

Question: When to use?
Answer: When Object creation is expensive than copying. When you have a log of objects with very few state variables. You can opt to just clone() them than creating new objects. 

Abstract Factory Pattern

Question: Why do we need to abstract out our factory ? 
Answer: Sometimes we can have a situation where we would want to club a bunch of objects together. Which may need each other to work fundamentally. e.g I have my app written to work on both Mobile and a Kiosk. But the objects created for both of these environment are totally different from each other, but as a group they need each other to work. 

interface King{
   String getName();
}

interface Castle{
   Location getLocation();
}

interface Army{
  int getSize();
}

Now there can be several kingdoms. Which will be the concrete classes of each of these interfaces.

say,

1. Marwar Kingdom has: MarwarKing, MarwarCastle and MarwarArmy concrete implementations.
2. Mughal Kingdom has: MughalKing, MughalCastle and MughalArmy concrete implementations.
3. British Kingdom has: BritishKing, BritishCastle and BritishArmy concrete implementations.

A greedy and Smart Software enginner for dynasty wants to sell his software solution to all of these dynasties, without making any change to his code. So It would make sense for him to just abstract out the Kingdom Factory. 

interface Kingdom{
      Army getArmy();
      Castle getCastle();
      King getKing();
}

class KingdomMaker{
   Kingdom makeKingdom(String kingdomName){
      // if else to make MarwarKingdom, Mughal or BritishKingdom according to the argument.
   }
}

'Client code: 
Kingdom kingdom = KingdomMaker.getKingdom("Marwar");
String kingName = kingdom.getKing.getName();