Design Patterns

Design Patterns in Java
  1. What is desing pattern?
  2. Advantage of desing pattern
  3. Types of desing pattern
A design pattern is a well-proved solution for solving the specific problem/task.
Design patterns are programming language independent strategies for solving the common object-oriented design problems. That means, a design pattern represents an idea, not a particular implementation.
By using the design patterns you can make your code more flexible, reusable and maintainable. It is the most important part because java internally follows design patterns.
Understanding the problem without using Design Patterns
Now, a question will be arising in your mind what kind of specific problem? Let me explain by an example:
Problem Given:
Suppose you want to create a class for which only a single instance (or object) should be created and that single object can be used by all other classes.
Solution:
Singleton design pattern is the best solution of above specific problem. So, every design pattern has some specification or set of rules for solving the problems. What are those specifications, you will see later in the types of design patterns.
Advantage of design pattern
  1. They are reusable in multiple projects.
  2. They provide the solutions that help to define the system architecture.
  3. They capture the software engineering experiences.
  4. They provide transparency to the design of an application.
  5. They are well-proved and testified solutions since they have been built upon the knowledge and experience of expert software developers.
  6. Design patterns don't guarantee an absolute solution to a problem. They provide clarity to the system architecture and the possibility of building a better system.
When should we use the design patterns?
We must use the design patterns during the analysis and requirement phase of SDLC(Software Development Life Cycle).
Design patterns ease the analysis and requirement phase of SDLC by providing information based on prior hands-on experiences.
Types of design patterns
Basically, design patterns are categorized into two parts:
  1. Core java (or JavaSE) Design Patterns.
    • Creational Design Pattern
    • Structural Design Pattern
    • Behavioral Design Pattern
  2. JavaEE (J2EE) Design Patterns.
    • Presentation Layer Design Pattern
    • Business Layer Design Pattern
    • Data Layer Design Pattern











Core Java Design Patterns

In core java, there are mainly three types of design patterns, which are further divided into their sub-parts:

1.Creational Design Pattern

  1. Factory Pattern
  2. Abstract Factory Pattern
  3. Singleton Pattern
  4. Prototype Pattern
  5. Builder Pattern.

2. Structural Design Pattern

  1. Adapter Pattern
  2. Bridge Pattern
  3. Composite Pattern
  4. Decorator Pattern
  5. Facade Pattern
  6. Flyweight Pattern
  7. Proxy Pattern

3. Behavioral Design Pattern

  1. Chain Of Responsibility Pattern
  2. Command Pattern
  3. Interpreter Pattern
  4. Iterator Pattern
  5. Mediator Pattern
  6. Memento Pattern
  7. Observer Pattern
  8. State Pattern
  9. Strategy Pattern
  10. Template Pattern
  11. Visitor Pattern

Do you know?

  • Christopher Alexander was the first person who invented all the above Design Patterns in 1977.
  • But later the Gang of Four - Design patterns, elements of reusable object-oriented software book was written by a group of four persons named as Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides in 1995.
  • That's why all the above 23 Design Patterns are known as Gang of Four (GoF) Design Patterns.







Creational design patterns

Creational design patterns are concerned with the way of creating objects. These design patterns are used when a decision must be made at the time of instantiation of a class (i.e. creating an object of a class).
But everyone knows an object is created by using new keyword in java. For example:
  StudentRecord s1=new StudentRecord();
Hard-Coded code is not the good programming approach. Here, we are creating the instance by using the new keyword. Sometimes, the nature of the object must be changed according to the nature of the program. In such cases, we must get the help of creational design patterns to provide more general and flexible approach.

Types of creational design patterns

There are following 5 types of creational design patterns.
  1. Factory Method Pattern
  2. Abstract Factory Pattern
  3. Singleton Pattern
  4. Prototype Pattern
  5. Builder Pattern










Factory Method Pattern
A Factory Pattern or Factory Method Pattern says that just define an interface or abstract class for 
creating an object but let the subclasses decide which class to instantiate. In other words, 
subclasses are responsible to create the instance of the class.
The Factory Method Pattern is also known as Virtual Constructor.
Advantage of Factory Design Pattern
  • Factory Method Pattern allows the sub-classes to choose the type of objects to create.
  • It promotes the loose-coupling by eliminating the need to bind application-specific classes into the code. That means the code interacts solely with the resultant interface or abstract 
  • class, so that it will work with any classes that implement that interface or that extends that abstract class.
Usage of Factory Design Pattern
  • When a class doesn't know what sub-classes will be required to create
  • When a class wants that its sub-classes specify the objects to be created.
  • When the parent classes choose the creation of objects to its sub-classes.
UML for Factory Method Pattern
  • We are going to create a Plan abstract class and concrete classes that extends the Plan abstract class. A factory class GetPlanFactory is defined as a next step.
  • GenerateBill class will use GetPlanFactory to get a Plan object. It will pass information (DOMESTICPLAN / COMMERCIALPLAN / INSTITUTIONALPLAN) to GetPalnFactory to get the type of object it needs.

Calculate Electricity Bill : A Real World Example of Factory Method
Step 1: Create a Plan abstract class.
import java.io.*;   
abstract class Plan{
         protected double rate;
         abstract void getRate();

         public void calculateBill(int units){
              System.out.println(units*rate);
          }
}//end of Plan class.
Step 2: Create the concrete classes that extends Plan abstract class.
class  DomesticPlan extends Plan{
        //@override
         public void getRate(){
             rate=3.50;           
        }
   }//end of DomesticPlan class.
     class  CommercialPlan extends Plan{
        //@override
         public void getRate(){
             rate=7.50;
        }
   }//end of CommercialPlan class.
     class  InstitutionalPlan extends Plan{
        //@override
         public void getRate(){
             rate=5.50;
        }
   }//end of InstitutionalPlan class.
Step 3: Create a GetPlanFactory to generate object of concrete classes based on given information..
class GetPlanFactory{
       
   //use getPlan method to get object of type Plan
       public Plan getPlan(String planType){
            if(planType == null){
             return null;
            }
              if(planType.equalsIgnoreCase("DOMESTICPLAN")) {
                 return new DomesticPlan();
               }
           else if(planType.equalsIgnoreCase("COMMERCIALPLAN")){
                return new CommercialPlan();
            }
          else if(planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {
                return new InstitutionalPlan();
          }
      return null;
   }
}//end of GetPlanFactory class.
Step 4: Generate Bill by using the GetPlanFactory to get the object of concrete classes by passing an information such as type of plan DOMESTICPLAN or COMMERCIALPLAN or INSTITUTIONALPLAN.
import java.io.*; 
class GenerateBill{
    public static void main(String args[])throws IOException{
      GetPlanFactory planFactory = new GetPlanFactory();
     
      System.out.print("Enter the name of plan for which the bill will be generated: ");
      BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

      String planName=br.readLine();
      System.out.print("Enter the number of units for bill will be calculated: ");
      int units=Integer.parseInt(br.readLine());

      Plan p = planFactory.getPlan(planName);
      //call getRate() method and calculateBill()method of DomesticPaln.

       System.out.print("Bill amount for "+planName+" of  "+units+" units is: ");
           p.getRate();
           p.calculateBill(units);
            }
    }//end of GenerateBill class.




Output












Abstract Factory Pattern
Abstract Factory Pattern says that just define an interface or abstract class for creating
 families of related (or dependent) objects but without specifying their concrete sub-classes.
 That means Abstract Factory lets a class returns a factory of classes. So, this is the reason that Abstract Factory Pattern is one level higher than the Factory Pattern.
An Abstract Factory Pattern is also known as Kit.
Advantage of Abstract Factory Pattern
  • Abstract Factory Pattern isolates the client code from concrete (implementation) classes.
  • It eases the exchanging of object families.
  • It promotes consistency among objects.
Usage of Abstract Factory Pattern
  • When the system needs to be independent of how its object are created, composed, and represented.
  • When the family of related objects has to be used together, then this constraint needs to be enforced.
  • When you want to provide a library of objects that does not show implementations and only reveals interfaces.
  • When the system needs to be configured with one of a multiple family of objects.
UML for Abstract Factory Pattern
  • We are going to create a Bank interface and a Loan abstract class as well as their sub-classes.
  • Then we will create AbstractFactory class as next step.
  • Then after we will create concrete classes, BankFactory, and LoanFactory that will extends AbstractFactory class
  • After that, AbstractFactoryPatternExample class uses the FactoryCreator to get an object of AbstractFactory class.
  • See the diagram carefully which is given below:

Example of Abstract Factory Pattern
Here, we are calculating the loan payment for different banks like HDFC, ICICI, SBI etc.
Step 1: Create a Bank interface
import java.io.*;  
interface Bank{
        String getBankName();
}
Step 2: Create concrete classes that implement the Bank interface.
class HDFC implements Bank{
         private final String BNAME;
         public HDFC(){
                BNAME="HDFC BANK";
        }
        public String getBankName() {
                  return BNAME;
        }
}
class ICICI implements Bank{
       private final String BNAME;
       ICICI(){
                BNAME="ICICI BANK";
        }
        public String getBankName() {
                  return BNAME;
       }
}
class SBI implements Bank{
      private final String BNAME;
      public SBI(){
                BNAME="SBI BANK";
        }
       public String getBankName(){
                  return BNAME;
       }
}
Step 3: Create the Loan abstract class.
abstract class Loan{
   protected double rate;
   abstract void getInterestRate(double rate);
   public void calculateLoanPayment(double loanamount, int years)
   {
        /*
              to calculate the monthly loan payment i.e. EMI 
                           
              rate=annual interest rate/12*100;
              n=number of monthly installments;          
              1year=12 months.
              so, n=years*12;

            */
             
         double EMI;
         int n;

         n=years*12;
         rate=rate/1200;
   EMI=((rate*Math.pow((1+rate),n))/((Math.pow((1+rate),n))-1))*loanamount;

System.out.println("your monthly EMI is "+ EMI +" for the amount"+loanamount+" you have borrowed");  
 }
}// end of the Loan abstract class.
Step 4: Create concrete classes that extend the Loan abstract class..
class HomeLoan extends Loan{
     public void getInterestRate(double r){
         rate=r;
    }
}//End of the HomeLoan class.
class BussinessLoan extends Loan{
    public void getInterestRate(double r){
          rate=r;
     }

}//End of the BusssinessLoan class.
class EducationLoan extends Loan{
     public void getInterestRate(double r){
       rate=r;
 }
}//End of the EducationLoan class.
Step 5: Create an abstract class (i.e AbstractFactory) to get the factories for Bank and
              Loan Objects.
abstract class AbstractFactory{
  public abstract Bank getBank(String bank);
  public abstract Loan getLoan(String loan);
}
Step 6: Create the factory classes that inherit AbstractFactory class to generate the 
             object of concrete class based on given information.
class BankFactory extends AbstractFactory{
   public Bank getBank(String bank){
      if(bank == null){
         return null;
      }
      if(bank.equalsIgnoreCase("HDFC")){
         return new HDFC();
      } else if(bank.equalsIgnoreCase("ICICI")){
         return new ICICI();
      } else if(bank.equalsIgnoreCase("SBI")){
         return new SBI();
      }
      return null;
   }
  public Loan getLoan(String loan) {
      return null;
   }
}//End of the BankFactory class.
class LoanFactory extends AbstractFactory{
           public Bank getBank(String bank){
                return null;
          }
     
     public Loan getLoan(String loan){
      if(loan == null){
         return null;
      }
      if(loan.equalsIgnoreCase("Home")){
         return new HomeLoan();
      } else if(loan.equalsIgnoreCase("Business")){
         return new BussinessLoan();
      } else if(loan.equalsIgnoreCase("Education")){
         return new EducationLoan();
      }
      return null;
   }
  
}
Step 7: Create a FactoryCreator class to get the factories by passing an information such as 
             Bank or Loan.
class FactoryCreator {
     public static AbstractFactory getFactory(String choice){
      if(choice.equalsIgnoreCase("Bank")){
         return new BankFactory();
      } else if(choice.equalsIgnoreCase("Loan")){
         return new LoanFactory();
      }
      return null;
   }
}//End of the FactoryCreator.
Step 8: Use the FactoryCreator to get AbstractFactory in order to get factories of concrete classes 
             by passing an information such as type.
import java.io.*;
class AbstractFactoryPatternExample {
      public static void main(String args[])throws IOException {
    
      BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

      System.out.print("Enter the name of Bank from where you want to take 
                       loan amount: ");
      String bankName=br.readLine();

System.out.print("\n");
System.out.print("Enter the type of loan e.g. home loan or business loan or education loan : ");

String loanName=br.readLine();
AbstractFactory bankFactory = FactoryCreator.getFactory("Bank");
Bank b=bankFactory.getBank(bankName);

System.out.print("\n");
System.out.print("Enter the interest rate for "+b.getBankName()+ ": ");

double rate=Double.parseDouble(br.readLine());
System.out.print("\n");
System.out.print("Enter the loan amount you want to take: ");

double loanAmount=Double.parseDouble(br.readLine());
System.out.print("\n");
System.out.print("Enter the number of years to pay your entire loan amount:");
int years=Integer.parseInt(br.readLine());

System.out.print("\n");
System.out.println("you are taking the loan from "+ b.getBankName());

AbstractFactory loanFactory = FactoryCreator.getFactory("Loan");
           Loan l=loanFactory.getLoan(loanName);
           l.getInterestRate(rate);
           l.calculateLoanPayment(loanAmount,years);
  }
}//End of the  AbstractFactoryPatternExample

Output







No comments:

Post a Comment