Showing posts with label Design pattern in java. Show all posts
Showing posts with label Design pattern in java. Show all posts

Thursday, 27 July 2023

Strategy Design Pattern

       In this post, we need to learn Strategy Design pattern with real time examples. For all design pattern posts refer - Design Patterns
      
      Strategy design pattern is one of the behavioral design pattern. Strategy pattern is used when we have multiple algorithms for a specific task and client decides the actual implementation to be used at runtime. Strategy pattern provides more flexibility, extensibility, and choice.

     There are many real time examples like payment implementation for different payment types,  different sorting algorithms and many more.

     I will take a GST tax example and will discuss in more detail with code, so GST tax varies between each products. There are four slabs - 5% GST, 12%GST, 18% GST and 28% GST(currently it's four slabs, it might change in future) and some of products doesn't have GST I mean it's a zero slab, but for code implementation we are not considering that. 

      Instead of creating and writing logic in four different classes for each slab, we need to follow the Strategy design pattern it's more flexible, readable and reusable code and also it follows the  OOP's design principle.

First step is to create a interface and then for each slab need to create seperate class and implements the interface.

TaxCalculation.java

public interface TaxCalculation {
     public Double calculateTax(Double productPrice);
}

Implemented classes, the overriden method calculateTax method logic will differ for each slab.

FivePercentageTax.java

public class FivePercentageTax implements TaxCalculation{

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 5) / 100;
	}

}

TwelvePercentageTax.java

public class TwelvePercentageTax implements TaxCalculation{

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 12) / 100;
	}

}

EighteenPercentageTax.java

public class EighteenPercentageTax implements TaxCalculation {

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 18) / 100;
	}

}

TwentyEightPercentageTax.java

public class TwentyEightPercentageTax implements TaxCalculation {

	@Override
	public Double calculateTax(Double productPrice) {
		return (productPrice * 28) / 100;
	}

}

The below class - GSTTaxCalculator is the main class where I created a method calculateGSTTax, in this need to pass the TaxCalculation implemented class object and using object we can call the claculateTax method it should invoke corresponding tax implementation method.

GSTTaxCalculator.java

public class GSTTaxCalculator {
	
     public double taxAmount;

     public void calculateGSTTax(TaxCalculation taxCalculation, double productPrice) {
	   this.taxAmount = taxCalculation.calculateTax(productPrice);
     }
}

StrategyDesignPatternDemo.java is a demo class to show the Strategy design outcome. So in your code implemention you just need to invoke above class - GSTTaxCalculator method using object and pass TaxCalculation implemented class object and also to pass the item price, it's just an example. We need to implement the Strategy Design pattern as per your requirement and scenario's.

StrategyDesignPatternDemo.java

public class StrategyDesignPatternDemo {
	
	public static void main(String[] args) {
		
		GSTTaxCalculator gstTaxCalculator = new GSTTaxCalculator();
		
		gstTaxCalculator.calculateGSTTax(new FivePercentageTax(), 250);
		System.out.println("GST tax for 5% slab - "+gstTaxCalculator.taxAmount);
		
		gstTaxCalculator.calculateGSTTax(new TwelvePercentageTax(), 250);
		System.out.println("GST tax for 12% slab - "+gstTaxCalculator.taxAmount);
		
		gstTaxCalculator.calculateGSTTax(new EighteenPercentageTax(), 250);
		System.out.println("GST tax for 18% slab - "+gstTaxCalculator.taxAmount);
		
		gstTaxCalculator.calculateGSTTax(new TwentyEightPercentageTax(), 250);
		System.out.println("GST tax for 28% slab - "+gstTaxCalculator.taxAmount);
	}
}

Output:- GST tax for 5% slab - 12.5
              GST tax for 12% slab - 30.0
              GST tax for 18% slab - 45.0
              GST tax for 28% slab - 70.0


Thank you for visiting the blog.

Friday, 9 July 2021

SOLID Design Principles with Examples

       In this post, we w'll learn the SOLID Principles with example for each principle and also to learn how to use these principles in our daily basis coding.
      
       SOLID Principles is a coding standard that all developers should follow these principles while developing any software. It was promoted by Robert C Martin and is used across the object-oriented design spectrum. When you apply SOLID principles properly in your software, it makes your code more extendable, logical, and easier to read.
      
      When the developer builds software following a bad design, the code can become inflexible and more brittle. Small changes in the software can result in bugs. For these reasons, we should follow SOLID Principles.

      It takes some time to understand, but when you follow these principles, it will improve the code quality and help you to understand the most well designed software.

Solid Design Principles in java


Let us discuss one by one in detail,

1) Single Responsibility Principle

     The Single Responsibility Principle(SRP) says that a class should have only one reason to change, which means every class should have a single responsibility or single job or single purpose.

     If single class handles multiple functionalities then in future if we do any modification then it will impact whole class not only the enhanced functionality so need to avoid this.

    The below example - Customer has the customer details like name, dateOfBirth, age, address, pinCode, phoneNumber and countryCode. As SRP principle states that class should have single responsibility but here if we do any validations on phoneNumber or address we need to do modify the complete Customer class and also it has different responsibility. So it voilates the Single Responsibility Principle.



 















The above class voilates the Single Responsibility Principle as we have address and phone detail fields are present in the same class.

    So those fields need to seperate into different classes and have to call in the customer class as follow.

 The updated customer class is below,

         If any enhancement comes in the future like do some validation on phoneNumber or address then we do modification on Phone or Address class so we can not do any modification on Customer class so this is what the SRP principle says(every class has single responsibility).


2) Open/Closed Principle

      The open/closed principle(OCP) states that a module or entity should be open for extension but closed for modification. It is one of the famous solid principles and very important in object oriented design principle.

       Bertrand Meyer says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification”.

Open for extension means we need to design the software modules/classes in such a way that the new responsibilities or functionalities should be added easily when new requirements come.
On other hand, Closed for modification means we should not modify the class/module until we find some bugs.

Example of voilation of Open/Closed Principle:--

       In the below Payment class, there is paymentType parameter, based on this we have payment processing logic for different payment types. But in future if any enhancement comes for new payment type then we need to modify the Payment class so this voilates OCP principle.

public class Payment {
	
	public void paymentProcessing(int amount, String paymentMode) {
		
		if (paymentMode.equals("Cash")) {
			//payment process for cash
			
		} else if (paymentMode.equals("CreditCard")) {
			//payment process for creditcard
			
		} else if (paymentMode.equals("debitCard")) {
			//payment process for debitCard
			
		}
	}
}

Example to followed the Open/Closed Principle:-

In the above example voilates OCP principle, need to follow OCP Principle as follows,

public interface PaymentType {
	
	public void processPayment();
	
}

class Cash implements PaymentType {

	@Override
	public void processPayment() {
		//add cash processing logic
	}
}

class DebitCard implements PaymentType {

	@Override
	public void processPayment() {
		//add debitcard processing logic
	}
}

        In the above example, created interface PaymentType and implemented classes are Cash and DebitCard so here if in future any enhancement for new paymentType then no need to modify the existing classes/interface instead create new implemented class and implement the required payment process logic.


3) Liskov Substitution Principle(LSP)

     Liskov Substitution Principle(LSP) is a third SOLID design principle and this defined by Barbara Liskov. It extends the Open/Closed principle and enables you to replace objects of a parent class with objects of a subclass without breaking the application. This requires all subclasses to behave in the same way as the parent class.

The Principle states that, objects of a superclass shall be replaceable with objects of its subclass without breaking the application.
That requires the objects of your subclasses to behave in the same way as the objects of your superclasses.

Example:-

     In the below example, the Square is derived class extends Rectangle class, where we can set the height and width.

public class Rectangle {
    private double height;
    private double width;
    public void setHeight(double h) { height = h; }
    public void setWidht(double w) { width = w; }
    ...
}
public class Square extends Rectangle {
    public void setHeight(double h) {
        super.setHeight(h);
        super.setWidth(w);
    }
    public void setWidth(double h) {
        super.setHeight(h);
        super.setWidth(w);
    }
}

        The above code not follow's LSP because you cannot replace the Rectangle base class with its derived class Square. The Square class has extra constraints, i.e., the height and width must be the same. Therefore, substituting Rectangle with Square class may result in unexpected behavior.

     This principle is just an extension of the Open Close Principle and it means that we must make sure that new derived classes are extending the base classes without changing their behavior.


4) Interface Segregation Principle

According to Robert Martin,

     The Interface Segregation Interface Principle states that, Clients should not be forced to depend upon interfaces that they do not use.

     The main aim of this principle is to break the larger application interfaces into smaller one and each interface serves the single purpose/responsibility, it's similar to single responsiblity principle. In Clients code I mean implemented classes, if any unimplemented methods we need to override those methods also, those are really not needed so this voilates Interface Segregation Principle.

Precise application design and correct abstraction is the key behind the Interface Segregation Principle. Though it'll take more time and effort in the design phase of an application and might increase the code complexity, in the end, we get a flexible code.

Let us see below example,

The HotelOrder has an interface and there are four abstract methods, onlineOrder() , walkInCustomerOrder(), onlinePayment() and cashPayment(). 

public interface HotelOrder {
	
    public void onlineOrder();
	
    public void walkInCustomerOrder();
	
    public void onlinePayment();
	
    public void cashPayment();
}

      There are two implemented classes for HotelOrder interface i.e WalkInCustomerOrder and OnlineCustomerOrder. For WalkInCustomerOrder implementation of onlineOrder() method is not needed but HotelOrder is an interface and we need to implement all abstract methods even those methods do not use. Samething for OnlineCustomerOrder, for online customers implementation class, don't need to implement the abstract method(walkInCustomerOrder()). 

public class OnlineCustomerOrder implements HotelOrder {

	@Override
	public void onlineOrder() {
		// code logic for online order
	}

	@Override
	public void walkInCustomerOrder() {
		//this method implementation is not needed for 
		//online customers
		throw new UnsupportedOperationException();
	}

	@Override
	public void onlinePayment() {
		//write a code for online payment
		//like calling payment gateway(payment stuffs)
	}

	@Override
	public void cashPayment() {
		//this method is not needed for online order customers
		//just throw an exception
		throw new UnsupportedOperationException();
	}
	
}

public class WalkInCustomerOrder implements HotelOrder{

	@Override
	public void onlineOrder() {
		//this method implementation is not needed
		throw new UnsupportedOperationException();
	}

	@Override
	public void walkInCustomerOrder() {
		//logic for walkIn Customer order
	}

	@Override
	public void onlinePayment() {
		//this method implementation is not needed
		throw new UnsupportedOperationException();
	}

	@Override
	public void cashPayment() {
		//logic for cash payments
	}

}

     The above code violates Interface Segregation Principle, as principle says client should not override methods those they do not use.

Code to follow Interface Segregation Principle:-

Create two interfaces one with WalkIn customer and second with Online Customer, In walkin customer interface define the walkin customer related methods like walkInCustomerOrder() and cashPayment() and for online customer interface define the onlinePayment() and onlineOrder() methods so that it follows the principle and no need to override unnecessary methods in the implemented classes.

public interface OnlineCustomerHotelOrder {

	public void onlineOrder();
		
	public void onlinePayment();
}

public interface WalkInCustomerHotelOrder {
		
	public void walkInCustomerOrder();
		
	public void cashPayment();
}

Implemented classes for each order,

public class OnlineCustomerOrder implements OnlineCustomerHotelOrder {

	@Override
	public void onlineOrder() {
		// code logic for online order
	}

	@Override
	public void onlinePayment() {
		//write a code for online payment
		//like calling payment gateway(payment stuffs)
	}
}

public class WalkInCustomerOrder implements WalkInCustomerHotelOrder{

	@Override
	public void walkInCustomerOrder() {
		//logic for walkIn Customer order
	}

	@Override
	public void cashPayment() {
		//logic for cash payments
	}
}


5) Dependency Inversion Principle

The Dependency Inversion Principle is also one of Solid Principle and it concers the relationship between modules and classes.

According to Robert Martin,

The Dependency Inversion Principle says that,
  • High-level modules should not depend on low-level modules. Both should depend on abstractions.
  • Abstractions should not depend on details. Details should depend on abstractions.
Lets see below example,

The TaxCalculator is main class to calculate the different types of tax like GST, Income Tax, Professional tax and so on. In the below example, I have given two types of taxes GST and Income tax and corresponding implemented classes for each tax types.

public class TaxCalculator {
	
	public static void taxCalculator(String mode) {
		if (mode.equals("GST")) {
			GSTTaxCalculator.calculate();
		} else if (mode.equals("IncomeTax")) {
			IncomeTaxCalculator.calculate();
		}
	}
}

class GSTTaxCalculator {
	
	public static void calculate() {
		// logic to calculate GST tax
	}
}

class IncomeTaxCalculator {
	
	public static void calculate() {
		//logic to calculate IncomeTax
	}
}

In the code, in future if  we need to implement any new tax type then need to modify the main class so it voilates the Dependency Inversion Principle. The implemented class depends on main module/class so that also voilates the principle.

Need to modify the abstract class not the  main class and also implemented class/module depends on abstraction not on main module/class.

Code to follow Dependency Inversion Principle:-

Create an interface Itax and both IncomeTaxCalculator and GSTTaxCalculator implements Itax interface.

public class TaxCalculator {
		
	public static void taxCalculator(Itax itax) {
		itax.calculate();
	}
}

interface Itax {
	public void calculate();
}

class GSTTaxCalculator implements  Itax{
	
	public void calculate() {
		// logic to calculate GST tax
	}
}

class IncomeTaxCalculator implements Itax{
	
	public void calculate() {
		//logic to calculate IncomeTax
	}
}

If any question or clarification or suggestion put comment in the comment section or send an email to me anilnivargi49@gmail.com

Thank you for visting blog.

Thursday, 25 July 2019

How to prevent Singleton Pattern from Reflection, Deserialization and Cloning ?

        In earlier posts, we discussed how to create the Singleton Design Pattern and what are the different approaches to create Singleton design pattern in Java. As we know that in singleton design pattern we can create only one instance and can access in whole application. But in some cases, it will break the singleton behavior.   

      There are mainly 3 concepts which can break singleton property of a singleton class. We can discuss how it can break and how to prevent from above concepts as below.


  • Reflection 
        Using Reflection API we can create multiple objects in singleton class. Consider the following example.

Example to show how reflection can break the singleton pattern:-

Singleton.java,

package com.example.demo;

public class Singleton {
 
        private static Singleton instance = null;
 
        private Singleton() {
  
        }
 
        public static Singleton getInstance() {
                if (instance == null) {
                         synchronized (Singleton.class) {
                                    if (instance == null) {
                                            instance = new Singleton();
                                    }
                         }
                 }
                 return instance;
         }
}

Using Reflection, we can break the above Singleton principle as shown in the below code.

package com.example.demo;

import java.lang.reflect.Constructor;

public class ReflectionSingleton {
 
         public static void main(String[] args) {
                   
                  Singleton objOne = Singleton.getInstance();
                  Singleton objTwo = null;
                  try {
                         Constructor constructor = Singleton.class.getDeclaredConstructor();
                         constructor.setAccessible(true);
                         objTwo = (Singleton) constructor.newInstance();
                   } catch (Exception ex) {
                            System.out.println(ex);
                   }
  
                   System.out.println("Hashcode of Object 1 - "+objOne.hashCode());
                   System.out.println("Hashcode of Object 2 - "+objTwo.hashCode());
         }

}

Output:-
Hashcode of Object 1 - 366712642
Hashcode of Object 2 - 1829164700

Same Singleton instances have different hashcodes so it breaks Singleton Principle.

How to Prevent Singleton pattern from Reflection:-

         There are many ways to prevent Singleton pattern from Reflection API, but one of best solution is to throw run time exception in constructor if instance is already exists. In this we can not able to create second instance.

Code:-
private Singleton() throws Exception {
        if (instance != null) {
                   throw new RuntimeException("Instance already exists");
        }
}


  • Deserialization
        In serialization we can save the object of byte stream into a file or send over a network. Suppose if you serialize the Singleton class and then again de-serialize that object will create new instance, hence deserialization will break the Singleton pattern.

Below code is to illustrate how Singleton pattern breaks,


package com.example.demo;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

public class DeserializationSingleton {
 
         public static void main(String[] args) throws Exception {
  
                   Singleton instanceOne = Singleton.getInstance(); 
                   ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.text")); 
                   out.writeObject(instanceOne); 
                   out.close(); 
  
                   ObjectInput in = new ObjectInputStream(new FileInputStream("file.text")); 
                   Singleton instanceTwo = (Singleton) in.readObject(); 
                   in.close(); 
  
                    System.out.println("hashCode of instanceOne is - " + instanceOne.hashCode()); 
                    System.out.println("hashCode of instanceTwo is - " + instanceTwo.hashCode()); 
          }  

}

Output:-
hashCode of instanceOne is - 1550089733
hashCode of instanceTwo is - 2003749087

As we see above output, there are two objects got created because hashcodes of instanceOne and instanceTwo are different, hence it breaks singleton principle.


Prevent Singleton Pattern from Deserialization:-

To overcome this issue, we need to override readResolve() method in Singleton class and return same Singleton instance.

Singleton.java,

   @override
     protected Object readResolve() { 
           return instance; 
     } 

Now run above DeserializationDemo class and see the output,
hashCode of instanceOne is - 1550089733
hashCode of instanceTwo is - 1550089733


  • Cloning
        Using clone method we can create copy of original object, samething if we applied clone in singleton pattern, it will create two instances one original and another one cloned object. In this case will break Singleton principle as shown in below code.

Implement Cloneable interface and override clone method in the above Singleton class.

Singleton.java
  .....
  @Override
  protected Object clone() throws CloneNotSupportedException  { 
          return super.clone(); 
  } 
....

Main Class,
package com.example.demo;

public class CloningSingleton {
 
        public static void main(String[] args) throws CloneNotSupportedException, Exception {
                 Singleton instanceOne = Singleton.getInstance();
                 Singleton instanceTwo = (Singleton) instanceOne.clone();
                 System.out.println("hashCode of instance1 - "+instanceOne.hashCode());
                 System.out.println("hashCode of instance2 - "+instanceTwo.hashCode());
        }

}

Output:-
hashCode of instance1 - 366712642
hashCode of instance2 - 1829164700


If we see above output, two instances have different hascodes means these instances are not same. 


Prevent Singleton Pattern from Cloning:-

In the above code, breaks the Singleton principle i. e created two instances. To overcome above issue we need to implement/override clone() method and throw an exception i.e CloneNotSupportedException from clone method. If anyone try to create clone object of Singleton, it will throw an exception as see below code.

Singleton.java
  ......
  @Override
  protected Object clone() throws CloneNotSupportedException  { 
           throw new CloneNotSupportedException(); 
  } 
........

Now you can run the main class, it will throw CloneNotSupportedException while creating clone object of Singleton object.


Thank you for visiting blog...


Related Posts:--
1) Singleton Design Pattern in java with example
2) Factory Design Pattern in Java
3) Builder Design Pattern in Java

Friday, 24 May 2019

Builder Design Pattern in Java

        The  Design Pattern is an important question for the experienced(4+ exp) candidates.  For freshers interviewer will check the Singleton or Factory design pattern knowledge but when comes to experience we need to know other design patterns also. In the current post, we will discuss one of the important design pattern i.e Builder Design Pattern. 

Read Top Java blogs, Feedspot Top 40 Java Blogs


What is Builder Design Pattern? 

According to wikipedia definition:-

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

It is used to construct a complex object step by step and the final step will return the object.

When to use ?

 Following are the conditions where we can use builder design pattern,
  • When multiple representation of objects are required.
  • Number of parameter required in constructor is more than manageable(more than 4 or 5)
  • Object creation contains optional parameter.

Guidelines to create the Builder Design Pattern:-

1) Create a static builder class inside the class whose object is to be build by the builder. EmployeeBuilder class is a static class created as in the example.

2) Builder class should have public constructor  with required parameters and outside class should have private constructor. All fields of class should be private.

3) Needs to write methods to get the values of optionalparameters. 
e.g withFieldPhone(), withFieldAddress and withFieldDateOfBirth().
In example, phone,address and dob are optional parameters.

4) Create builder method in the builder class to get the desired object.

Example:--

Employee.java,

package com.test;

public class Employee {
 
     private int id;
     private String name;
     private int age;
     private String phone;
     private String address;
     private String dob;
 
     private Employee(EmployeeBuilder builder) {
         this.id = builder.id;
         this.name = builder.name;
         this.age = builder.age;
         this.phone = builder.phone;
         this.address = builder.address;
         this.dob = builder.dob;
     }
 
     public int getId() {
         return id;
     }

     public String getName() {
         return name;
     }

     public int getAge() {
         return age;
     }

     public String getPhone() {
         return phone;
     }

     public String getAddress() {
         return address;
     }

     public String getDob() {
         return dob;
     }

     public static class EmployeeBuilder {
  
         private int id;
         private String name;
         private int age;
         private String phone;
         private String address;
         private String dob;
  
         //id, name and age are manadatory fields 
         public EmployeeBuilder(int id, String name, int age) {
             this.id = id;
             this.name = name;
             this.age = age;
         }
  
         public EmployeeBuilder withFieldPhone(String phone) {
             this.phone = phone;
             return this;
         }
  
         public EmployeeBuilder withFieldAddress(String address) {
             this.address = address;
             return this;
         }
  
         public EmployeeBuilder withFieldDateOfBirth(String dob) {
             this.dob = dob;
             return this;
         }
  
         public Employee build() {
             return new Employee(this);
         }
    }    
 
     @Override 
     public String toString() { 
         return "Id - "+id+", Name - "+name+", age - "+age+ ",address - "+ address+
          ", Phone - "+phone; 
     }
  
}

The above code is an example of Builder Design pattern, Now this we can access in below code.

BuilderDesignPatternEx.java,

package com.test;

public class BuilderDesignPatternEx {
 
     public static void main(String[] args) {
         Employee pattern = new Employee.EmployeeBuilder(10, "Kiran",10).withFieldAddress("Sonyal").build();
         System.out.println(pattern);
         //System.out.println(pattern.getName());
     }

}

Output:--

Id - 10, Name - Kiran, age - 10,address - Sonyal, Phone - null


Java built in builder design pattern examples:

StringBuilder and StringBuffer classes are internally used builder design pattern concept.

Thank you for visiting blog..