Showing posts with label Design Pattern. Show all posts
Showing posts with label Design Pattern. Show all posts

Saturday, May 14, 2022

Spring Bean Scopes

 Spring Singleton Scope : Singleton in Spring guarantees to create only one bean instance for given bean per id definition per container.  that means if we define same bean with two id or name than two instance world be created.

Spring singleton pattern is different from gang of four singleton pattern. While gang of four Singleton pattern ensures that one and only one instance is created per ClassLoader.

Example : Bean define only once but calling two times. So its return same instance of  same bean.

package com.example.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import com.example.app.model.User;

@SpringBootApplication
public class SpringBootApp {
	public static void main(String[] args) {
		ApplicationContext appContaxt = SpringApplication.run(SpringBootApp.class, args);

		User objUser1 = appContaxt.getBean("user", User.class);
		System.out.println("HadhCode for objUser1 : " + objUser1.hashCode());

		User objUser2 = appContaxt.getBean("user", User.class);
		System.out.println("HashCode for objUser2 : " + objUser2.hashCode());
	}

	@Bean(name = "user")
	public User user() {
		return new User();
	}
}

Output : 

HadhCode for objUser1 : 1413858762
HashCode for objUser2 : 1413858762

As you can see in the above example we have define user bean only once and it is bydefault singleton. and we call bean 2 times but its return same bean as it returns same hashCode.

Example : same bean(Singletone bean) with two different id or name.

package com.example.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import com.example.app.model.User;

@SpringBootApplication
public class SpringBootApp {
	public static void main(String[] args) {
		ApplicationContext appContaxt = SpringApplication.run(SpringBootApp.class, args);

		User objUser1 = appContaxt.getBean("user", User.class);
		System.out.println("HadhCode for objUser1 : " + objUser1.hashCode());

		User objUser2 = appContaxt.getBean("user1", User.class);
		System.out.println("HashCode for objUser2 : " + objUser2.hashCode());
	}

	@Bean(name = "user")
	public User user() {
		return new User();
	}
	
	@Bean(name = "user1")
	public User user1() {
		return new User();
	}
}

Output : 

HadhCode for objUser1 : 1739989024
HashCode for objUser2 : 2063549093

As you see in the output of above program if we define same been (singletone been) with two different id or name then two instance of bean would be created. As it returns different hashCode.

Example Prototype scope :

package com.example.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;

import com.example.app.model.User;

@SpringBootApplication
public class SpringBootApp {
	public static void main(String[] args) {
		ApplicationContext appContaxt = SpringApplication.run(SpringBootApp.class, args);

		User objUser1 = appContaxt.getBean("user", User.class);
		System.out.println("Prototype been : HadhCode for objUser1 : " + objUser1.hashCode());

		User objUser2 = appContaxt.getBean("user", User.class);
		System.out.println("Prototype been : HashCode for objUser2 : " + objUser2.hashCode());
	}

	@Bean(name = "user")
	@Scope("prototype")
	public User user() {
		return new User();
	}
}

Output of prototype bean scope : 

Prototype been : HadhCode for objUser1 : 1573752639
Prototype been : HashCode for objUser2 : 1245794392

As you can seen in the output of bean while scope of bean is prototype. we have define bean only once but while calling bean two time and its returns different hashCode that means its create new instance every time while we call prototype bean in spring.

Friday, May 13, 2022

Design Patterns Used In Spring Framework

 Design Patterns used in Spring Framework

  • Proxy pattern
  • Singleton pattern
  • Factory Method pattern
  • Template pattern
  • MVC Pattern
  • FrontController Pattern
  • View Helper Pattern
  • DI/IOC Pattern
  • Service Locator Pattern
  • Observer-Observable
  • Context Object Pattern

Microservices Design Patterns

 Below are design patterns using in microservices in spring boot.

  • Singleton pattern
  • Factory Method pattern
  • Proxy pattern
  • Template pattern
  • Prototype Pattern
  • DI/IOC Pattern
  • Chain of Responsibility Design Pattern : This design pattern is used where we are using multiple webservices where output of one service is input of other service so on..
  • View Helper Pattern
  • FrontController Pattern
  • Decomposition Patterns : 
    • Decompose by Business Capability
    • Decompose by Subdomain
    • Decompose by Transactions / Two-phase commit (2pc) pattern
  • Strangler Pattern
  • Integration Patterns
    • API Gateway Pattern
    • Aggregator Pattern
    • Client-Side UI Composition Pattern
  • Database Patterns
  • Database per Service
    • Shared Database per Service
    • Command Query Responsibility Segregation (CQRS)
    • Saga Pattern
  • Observability Patterns
    • Log Aggregation
    • Performance Metrics
    • Distributed Tracing
    • Health Check
  • Cross-Cutting Concern Patterns
    • External Configuration
    • Service Discovery Pattern
    • Circuit Breaker Pattern
    • Blue-Green Deployment Pattern

Thursday, December 16, 2021

Reflection, Serialization and Cloning Prevent in Singleton Pattern

Q:- What is singletone class in java? Nubmer of ways to create singletone class in java?

Answer:- if you don't know about singletone class please read - Singletone class in java

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

Reflection: Reflection can break the singleton property of singleton class, as we can change the accessible using setAccessible true using reflection as shown in following example:
package com.javaiq.singletone.reflection;

import java.lang.reflect.Constructor;

//Singleton class
class Singleton {
	// public instance initialized when loading the class
	public static Singleton instance = new Singleton();

	private Singleton() {
		// private constructor
	}
}

public class SingletonReflectionTest {

	public static void main(String[] args) {
		Singleton instance1 = Singleton.instance;
		Singleton instance2 = null;
		try {
			Constructor[] constructors = Singleton.class.getDeclaredConstructors();
			for (Constructor constructor : constructors) {
				// Below code will destroy the singleton pattern
				constructor.setAccessible(true);
				instance2 = (Singleton) constructor.newInstance();
				break;
			}
		}

		catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("hashCode of instance1:- " + instance1.hashCode());
		System.out.println("hashCode of instance2:- " + instance2.hashCode());
	}
}
Output: As in below output we can see two instance of singletone class have different hascode that means, 2 objects of same class are created and singleton pattern has been destroyed.
hashCode of instance1:- 1829164700
hashCode of instance2:- 2018699554
Overcome reflection issue:To overcome reflection issue on singletone class, we can use enums because java ensures internally that enum value is instantiated only once. Since java Enums are globally accessible,So we can use enums for singletons. Its only drawback is that it is not flexible i.e it does not allow lazy initialization.
Enums. An enum is a special "class" that represents a group of constants (unchangeable variables, like final variables).
package com.javaiq.in;

public enum Singleton 
{
  INSTANCE;
}
package com.javaiq.singletone.reflection;

//Java code to Overcome reflection issue on Singleton property

import java.lang.reflect.Constructor;

public class SingletonOvercomeReflectionIssue {
	public static void main(String[] args) {
		Singleton instance1 = Singleton.INSTANCE;  // Using enum Singleton
		Singleton instance2 = null;
		try {
			Constructor[] constructors = Singleton.class.getDeclaredConstructors();
			for (Constructor constructor : constructors) {
				// Below code will destroy the singleton pattern
				constructor.setAccessible(true);
				instance2 = (Singleton) constructor.newInstance();
				break;
			}
		}

		catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("instance1.hashCode():- " + instance1.hashCode());
		System.out.println("instance2.hashCode():- " + instance2.hashCode());
	}
}
Output: It clear from below output by using enum we can not break singleton propery of singletone class by using reflection.
java.lang.IllegalArgumentException: Cannot reflectively create enum objects
	at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
	at com.javaiq.singletone.reflection.SingletonOvercomeReflectionIssue.main(SingletonOvercomeReflectionIssue.java:16)
instance1.hashCode():- 2018699554Exception in thread "main" java.lang.NullPointerException
	at com.javaiq.singletone.reflection.SingletonOvercomeReflectionIssue.main(SingletonOvercomeReflectionIssue.java:26)
Serialization: While doing Serialization on singleton classes it can also break the singleton property of singleton classes. Serialization is used to convert an object of byte stream and save in a file or send over a network. Suppose if we serialize an object of a singleton class and then if we de-serialize same object it will create a new instance and hence break the singleton pattern.
package com.javaiq.in;

//Java code to explain breakage of singleton property.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Singleton implements Serializable {
	// public instance initialized when loading the class
	public static Singleton instance = new Singleton();

	private Singleton() {
		// private constructor
	}
}

public class SingletonSerializationTest {

	public static void main(String[] args) {
		try {
			Singleton instance1 = Singleton.instance;
			ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.text"));
			out.writeObject(instance1);
			out.close();

			// deserialize from file to object
			ObjectInput in = new ObjectInputStream(new FileInputStream("file.text"));

			Singleton instance2 = (Singleton) in.readObject();
			in.close();

			System.out.println("hashCode of instance1:- " + instance1.hashCode());
			System.out.println("hashCode of instance2:- " + instance2.hashCode());
		}

		catch (Exception e) {
			e.printStackTrace();
		}
	}
}
Output: As clear from below output by serialization its break singletone property of singletone class.
hashCode of instance1:- 865113938
hashCode of instance2:- 250421012
Overcome serialization issue:To overcome serialization issue, we need to implement readResolve() method in singleton class and return same instance. 
readResolve() method:-For Serializable and Externalizable classes, the readResolve method allows a class to replace/resolve the object read from the stream before it is returned to the caller. By implementing the readResolve method, a class can directly control the types and instances of its own instances being deserialized.
package com.javaiq.singletone.serialization;

//Java code to Overcome serialization issue of Serialization on singleton classes
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Singleton implements Serializable {
	// public instance initialized when loading the class
	public static Singleton instance = new Singleton();

	private Singleton() {
		// private constructor
	}

	// we need to implement readResolve method
	protected Object readResolve() {
		return instance;
	}
}

public class SingletonOvercomeSerializationIssueTest {

	public static void main(String[] args) {
		try {
			Singleton instance1 = Singleton.instance;
			ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.text"));
			out.writeObject(instance1);
			out.close();

			// deserialize from file to object
			ObjectInput in = new ObjectInputStream(new FileInputStream("file.text"));
			Singleton instance2 = (Singleton) in.readObject();
			in.close();

			System.out.println("instance1 hashCode:- " + instance1.hashCode());
			System.out.println("instance2 hashCode:- " + instance2.hashCode());
		}

		catch (Exception e) {
			e.printStackTrace();
		}
	}
}
Output: Its clear from output we can safe singletone propery of singletone class by using readResolve() method.
instance1 hashCode:- 865113938
instance2 hashCode:- 865113938
Cloning: Cloning can also break singleton propery of singletone class. Cloning is a concept to create duplicate objects of same class. Using clone we can create copy of object. if we create clone of a singleton object, then it will create a copy (new object) that means now there are two instances of a singleton class, so the class is no more singleton.There are two way to overcone this issue.
package com.javaiq.singletone.cloning;

//Java code to cloning with singleton
class SuperClass implements Cloneable {
	int i = 10;

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

//Singleton class
class Singleton extends SuperClass {
//public instance initialized when loading the class
	public static Singleton instance = new Singleton();

	private Singleton() {
		// private constructor
	}
}

public class SingletonCloningTest {
	public static void main(String[] args) throws CloneNotSupportedException {
		Singleton instance1 = Singleton.instance;
		Singleton instance2 = (Singleton) instance1.clone();
		System.out.println("instance1 hashCode:- " + instance1.hashCode());
		System.out.println("instance2 hashCode:- " + instance2.hashCode());
	}
}
Output: As clear from below output by cloning its break singletone property of singletone class.
instance1 hashCode:- 1829164700
instance2 hashCode:- 2018699554
Overcome Cloning issue:- Way-1 - We can throw CloneNotSupportedException while clone object.
package com.javaiq.in;

//Java code to Overcome cloning issue with singleton
//Way-1 :  We can throw CloneNotSupportedException
class SuperClass implements Cloneable {
	int i = 10;

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

//Singleton class
class Singleton extends SuperClass {
//public instance initialized when loading the class
	public static Singleton instance = new Singleton();

	private Singleton() {
		// private constructor
	}

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

public class SingletonOvercomeCloningIssueTest1 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Singleton instance1 = Singleton.instance;
		Singleton instance2 = (Singleton) instance1.clone();
		System.out.println("instance1 hashCode:- " + instance1.hashCode());
		System.out.println("instance2 hashCode:- " + instance2.hashCode());
	}
}
Output: We can see in the output its throwing exception while we are trying to clone instance of singletone class.
Exception in thread "main" java.lang.CloneNotSupportedException
	at com.javaiq.in.Singleton.clone(SingletonOvercomeCloningIssueTest1.java:25)
	at com.javaiq.in.SingletonOvercomeCloningIssueTest1.main(SingletonOvercomeCloningIssueTest1.java:32)
Overcome Cloning issue:- Way-2 :- We can return same instance while override clone method.
package com.javaiq.singletone.cloning;

//Java code to overcome cloning issue with singleton.
//Way-2:  we can return same instance in clone
class SuperClass implements Cloneable {
	int i = 10;

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

//Singleton class
class Singleton extends SuperClass {
//public instance initialized when loading the class
	public static Singleton instance = new Singleton();

	private Singleton() {
		// private constructor
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return instance;
	}
}

public class SingletonOvercomeCloningIssueTest2 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Singleton instance1 = Singleton.instance;
		Singleton instance2 = (Singleton) instance1.clone();
		System.out.println("instance1 hashCode:- " + instance1.hashCode());
		System.out.println("instance2 hashCode:- " + instance2.hashCode());
	}
}
Output:
instance1 hashCode:- 1829164700
instance2 hashCode:- 1829164700

Tuesday, November 16, 2021

Design Patterns used in Spring Framework

 Design Patterns used in Spring Framework

  • MVC Pattern
  • Proxy Pattern
  • Factory Pattern
  • Singleton Pattern
  • Template method Patter
  • FrontController Pattern
  • View Helper Pattern
  • Prototype Pattern
  • DI/IOC Pattern

Design patterns used in spring boot microservices

 Design patterns used in spring boot microservices

  • Aggregator
  • API Gateway
  • Chained or Chain of Responsibility
  • Asynchronous Messaging
  • Database or Shared Data
  • Event Sourcing
  • Branch
  • Command Query Responsibility Segregator
  • Circuit Breaker
  • Decomposition

Design patterns used in Hibernate framework

 What are the design patterns used in Hibernate framework

  • Domain Model Pattern
  • Data Access Object (DAO) Design Pattern
  • Factory
  • Abstract Factory
  • Data Mapper
  • Proxy use for lazy loading
  • Object-Relational Mapping (ORM)
  • Query Object use for Criterion API
  • Facade

Saturday, December 28, 2019

Bridge Design Pattern

Bridge Design Pattern

A bridge is used to create seperate the implementation from the API. A bridge tends to be created to support pluggability of the implementation into different APIs.

The definition of Bridge Design Pattern provided by Gang of Four book on Design Patterns states:
“Decouple an abstraction from its implementation so that the two can vary independently.”

Friday, December 27, 2019

Adapter Design Pattern

Adapter Pattern
“Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.”
  • Adapter is a structural design pattern.
  • The adapter design pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is used to make existing classes work with others without modifying their source code.Which allows incompatible objects to collaborate.
  • The Adapter acts as a wrapper between two objects. It get data from one object and transforms them to format and interface recognizable by the second object.
  • Adapter pattern works as a bridge between two incompatible interfaces. 
  • An Adapter Pattern says that just "converts the interface of a class into another interface that a client wants".
  • An Adapter pattern acts as a connector between two incompatible interfaces that otherwise cannot be connected directly.
Adapter design pattern example:
Let's assume we have an existing student object and we want to convert this as employee object after candidate selection process completed.

Thursday, July 25, 2019

Chain Of Responsibility Design Pattern

Let's start "Chain of Responsibility design pattern".This is one of behavioral patterns in Gang Of four Design Pattern.
The definition of Chain of Responsibility pattern provided by Gang of Four book on Design Patterns states:
"Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it."

By using Chain of Responsibility design pattern. I am taking an example of currency.
Suppose i want to know,the number of currency(INR of  2000,500,200,100) will be return by ATM if All currency will be there.
Currency.java

package com.shubh.currency;

import com.shubh.currency.model.ATM;

public interface Currency {
 public void process(ATM atm);
 public void setNextCurrency(Currency nextCurrency);
}

Currency2000.java

package com.shubh.currency.impl;

import java.util.Map;
import com.shubh.currency.Currency;
import com.shubh.currency.model.ATM;

public class Currency2000 implements Currency {

 private int netAmount;
 private int withdraw;
 private int balance;
 private int numberOfCurrency;
 private int currencyValue = 2000;
 private Currency nextCurrency;

 public void process(ATM atm) {
  netAmount = atm.getAmount();
  balance = atm.getBalance();
  if (balance != 0 && netAmount > balance) {
   netAmount = balance;
  }
  if (netAmount >= currencyValue) {
   withdraw = netAmount - netAmount % currencyValue;
   numberOfCurrency = withdraw / currencyValue;
   balance = netAmount - withdraw;
   System.out.println("Currency: " + currencyValue + ": "
     + numberOfCurrency + ", Balance: " + balance);
   Map currencyDetails = atm.getCurrencyDetails();
   currencyDetails.put(currencyValue + "", numberOfCurrency);
   atm.setBalance(balance);
   atm.setCurrencyDetails(currencyDetails);
  }
  if (atm.getBalance() > 0) {
   nextCurrency.process(atm);
  }

 }

 public void setNextCurrency(Currency nextCurrency) {
  this.nextCurrency = nextCurrency;
 }
}
Currency500.java

package com.shubh.currency.impl;

import java.util.Map;

import com.shubh.currency.Currency;
import com.shubh.currency.model.ATM;

public class Currency500 implements Currency {

 private int netAmount;
 private int withdraw;
 private int balance;
 private int numberOfCurrency;
 private int currencyValue = 500;
 private Currency nextCurrency;

 public void process(ATM atm) {
  netAmount = atm.getAmount();
  balance = atm.getBalance();
  if (balance != 0 && netAmount > balance) {
   netAmount = balance;
  }
  if (netAmount >= currencyValue) {
   withdraw = netAmount - netAmount % currencyValue;
   numberOfCurrency = withdraw / currencyValue;
   balance = netAmount - withdraw;
   System.out.println("Currency: " + currencyValue + ": "
     + numberOfCurrency + ", Balance: " + balance);
   Map currencyDetails = atm.getCurrencyDetails();
   currencyDetails.put(currencyValue + "", numberOfCurrency);
   atm.setBalance(balance);
   atm.setCurrencyDetails(currencyDetails);
  }
  if (atm.getBalance() > 0) {
   nextCurrency.process(atm);
  }

 }

 public void setNextCurrency(Currency nextCurrency) {
  this.nextCurrency = nextCurrency;
 }
}
Currency200.java

package com.shubh.currency.impl;

import java.util.Map;
import com.shubh.currency.Currency;
import com.shubh.currency.model.ATM;

public class Currency200 implements Currency {

 private int netAmount;
 private int withdraw;
 private int balance;
 private int numberOfCurrency;
 private int currencyValue = 200;
 private Currency nextCurrency;

 public void process(ATM atm) {
  netAmount = atm.getAmount();
  balance = atm.getBalance();
  if (balance != 0 && netAmount > balance) {
   netAmount = balance;
  }
  if (netAmount >= currencyValue) {
   withdraw = netAmount - netAmount % currencyValue;
   numberOfCurrency = withdraw / currencyValue;
   balance = netAmount - withdraw;
   System.out.println("Currency: " + currencyValue + ": "
     + numberOfCurrency + ", Balance: " + balance);
   Map currencyDetails = atm.getCurrencyDetails();
   currencyDetails.put(currencyValue + "", numberOfCurrency);
   atm.setBalance(balance);
   atm.setCurrencyDetails(currencyDetails);
  }
  if (atm.getBalance() > 0) {
   nextCurrency.process(atm);
  }
 }

 public void setNextCurrency(Currency nextCurrency) {
  this.nextCurrency = nextCurrency;
 }
}
Currency100.java

package com.shubh.currency.impl;

import java.util.Map;
import com.shubh.currency.Currency;
import com.shubh.currency.model.ATM;

public class Currency100 implements Currency {

 private int netAmount;
 private int withdraw;
 private int balance;
 private int numberOfCurrency;
 private int currencyValue = 100;
 private Currency nextCurrency;

 public void process(ATM atm) {
  netAmount = atm.getAmount();
  balance = atm.getBalance();
  if (balance != 0 && netAmount > balance) {
   netAmount = balance;
  }
  if (netAmount >= currencyValue) {
   withdraw = netAmount - netAmount % currencyValue;
   numberOfCurrency = withdraw / currencyValue;
   balance = netAmount - withdraw;
   System.out.println("Currency: " + currencyValue + ": "
     + numberOfCurrency + ", Balance: " + balance);
   Map currencyDetails = atm.getCurrencyDetails();
   currencyDetails.put(currencyValue + "", numberOfCurrency);
   atm.setBalance(balance);
   atm.setCurrencyDetails(currencyDetails);
  }
  if (atm.getBalance() > 0) {
   // as we are not using currency less then 100 so no need for this.
   // nextCurrency.process(atm);
  }

 }

 public void setNextCurrency(Currency nextCurrency) {
  this.nextCurrency = nextCurrency;
 }
}
Let's Test:- CurrencyApplication.java

package com.shubh.application;

import com.shubh.currency.Currency;
import com.shubh.currency.impl.Currency100;
import com.shubh.currency.impl.Currency200;
import com.shubh.currency.impl.Currency2000;
import com.shubh.currency.impl.Currency500;
import com.shubh.currency.model.ATM;

public class CurrencyApplication {
 public static void main(String[] args) {

  System.out.println("Start Main.");
  Currency currency2000 = new Currency2000();
  Currency currency500 = new Currency500();
  Currency currency200 = new Currency200();
  Currency currency100 = new Currency100();

  // Set next object to process chain of objects
  currency2000.setNextCurrency(currency500);
  currency500.setNextCurrency(currency200);
  currency200.setNextCurrency(currency100);

  ATM atm = new ATM();
  atm.setAmount(2800);

  currency2000.process(atm);
  System.out.println(atm);
  System.out.println("End Main.");
 }
}
Outpot:-

Start Main.
Currency: 2000: 1, Balance: 800
Currency: 500: 1, Balance: 300
Currency: 200: 1, Balance: 100
Currency: 100: 1, Balance: 0
{100=1, 200=1, 500=1, 2000=1}
End Main.
As you can see in the output.
Input amount is Rs 2800/-. First request as been processed by the Currency2000. So Since we can't get more than one currency of Rs.2000/- So it will give one currency of 2000 and  the balance amount is Rs 800/-. Now request has been sent to Currency500 for balance amount Rs 800/- so on.

Monday, May 20, 2019

Builder Design Pattern

Builder Design Patterns

The definition of Builder Pattern provided by Gang of Four book on Design Patterns states:
Separate the construction of a complex object from its representation so that the same construction process can create different representations.

package com.shubh.builder.pattern;

public final class User {

 // required
 private final String firstName;
 // required
 private final String lastName;
 // required
 private final String email;
 private final int age;
 private final String phone;
 private final String address;

 private User(UserBuilder builder) {
  this.firstName = builder.firstName;
  this.lastName = builder.lastName;
  this.email = builder.email;
  this.age = builder.age;
  this.phone = builder.phone;
  this.address = builder.address;
 }

 public String getFirstName() {
  return firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public int getAge() {
  return age;
 }

 public String getPhone() {
  return phone;
 }

 public String getAddress() {
  return address;
 }

 public String getEmail() {
  return email;
 }

 @Override
 public String toString() {
  return "User [ First Name:" + this.firstName + ", Last Name: " + this.lastName + ", Email: " + this.email
    + ", Age: " + this.age + ", Phone: " + this.phone + ", Address: " + this.address + "]";
 }

 public static class UserBuilder {
  private final String firstName;
  private final String lastName;
  private final String email;
  private int age;
  private String phone;
  private String address;

  public UserBuilder(String firstName, String lastName, String email) {
   // as firstName, lastName, email are required fields
   this.firstName = firstName;
   this.lastName = lastName;
   this.email = email;
  }

  public UserBuilder age(int age) {
   this.age = age;
   return this;
  }

  public UserBuilder phone(String phone) {
   this.phone = phone;
   return this;
  }

  public UserBuilder address(String address) {
   this.address = address;
   return this;
  }

  // Return the finally consrcuted User object
  public User build() {
   User user = new User(this);
   validateUserObject(user);
   return user;
  }

  private void validateUserObject(User user) {
   // Do some code here for basic validations if required
  }
 }
}

Now test UserBuilder.

package com.shubh.builder.pattern;

public class UserBuilderTest {

 public static void main(String[] args) {
  
  // Create user with all attributes.
  User user1 = new User.UserBuilder("Sandeep", "kumar", "sandeep@xyz.com")
    .age(30).phone("1234567")
    .address("Test address 1234")
    .build();

  System.out.println(user1);

  // Create user without address.
  User user2 = new User.UserBuilder("Pankaj", "xyz", "pankaj@xyz.com")
    .age(40)
    .phone("5655")
    // no address
    .build();

  System.out.println(user2);

  // Create user only with required attributes
  User user3 = new User.UserBuilder("Admin", "Test", "admin@xyz.com")
    // No age
    // No phone
    // no address
    .build();

  System.out.println(user3);
 }
}
Output of above program.

User [ First Name:Sandeep, Last Name: kumar, Email: sandeep@xyz.com, Age: 30, Phone: 1234567, Address: Test address 1234]
User [ First Name:Pankaj, Last Name: xyz, Email: pankaj@xyz.com, Age: 40, Phone: 5655, Address: null]
User [ First Name:Admin, Last Name: Test, Email: admin@xyz.com, Age: 0, Phone: null, Address: null]
Q- When and Why to use Builder Desing Pattern?
  • Builder pattern is used to construct a complex object step by step and the final step will return the object.
  • Once required immutable object.
  • To avoids the problem of a constructor with a large number of parameters.
  • Builders are immutable objects and should not be modified once instantiated.  
  • Builders are best suitable for objects that can be live throughout the application lifecycle.
  • Use Builde where you need 'object that need other objects or "Parts" to construct them'.
  • Builder pattern solves the issue with large number of optional parameters and inconsistent state by providing a way to build the object step-by-step and provide a method that will actually return the final Object.
Q- What is the difference between builder and factory pattern? Or  builder Vs factory pattern?

Monday, May 6, 2019

Prototype Design Pattern In Java

Prototype Design Pattern

Q- How to create clone of object without using cloneable interface?
Q- Why clone method is not in cloneable interface?
Q- Why clone method is defined in object class?
Q- Why is the clone () method protected in Java Lang object?
Q- Why do we need to override clone method?
Q- How can we create object using clone method in Java?
Q- What does Super Clone do? Or What does super.clone() do?
Q- Does clone create new object in Java?
Q- Why do we need cloning in Java?
Q- Difference Between Shallow Copy Vs Deep Copy In Java
Q- Is Java clone a deep copy or shallow copy?
Q- Which of these method of object class can clone an object?

Proxy Design Pattern Example


Proxy Design Pattern

The definition of Proxy pattern  provided by Gang of Four book on Design Patterns states:
"Provide a surrogate or placeholder for another object to control access to it."
  • Proxy design pattern is one of Structural Design Pattern.
  • This design pattern is used to create a surrogate or wrapper "in place of" another object.
  • We can modify the functionalities of an object without modifying the actual object’s behavior.  
  • The Surrogate or wrapper object is known as proxy of actual object. So we have access controls to actual object.

Q- When to use Proxy Design Pattern ?
  • We can use Proxy design pattern when there is a requirement to access control to an Object.
  • when there is a need for a reference to an Object.
  • If we want to add/modify the object’s behavior without affecting actual object’s behavior.  
There are 4 common situations we can use proxy design pattern.
  • Remote proxy:
  • Virtual proxy
  • Protection proxy:
  • Smart Proxy


CollegeInternet.java
package com.shubh.dp.example;

public interface CollegeInternet {
 public void getInternet();
}


CollegeInternetImpl
package com.shubh.dp.example;

public class CollegeInternetImpl implements CollegeInternet {
 private String department;

 public CollegeInternetImpl(String detpName) {
  this.department = detpName;
 }

 @Override
 public void getInternet() {
  System.out.println("Internet has been connected successfully for Department: " + department);
 }
}


InternetProxy.java
package com.shubh.dp.example;

import java.util.ArrayList;
import java.util.List;

public class InternetProxy implements CollegeInternet {
 private String department;
 private CollegeInternet realObject;
 private List proxyLock = new ArrayList();

 public InternetProxy(String department) {
  this.department = department;
 }

 @Override
 public void getInternet() {
  if (!getProxyLock().contains(department)) {
   realObject = new CollegeInternetImpl(department);
   realObject.getInternet();
  } else {
   System.out.println("Internet access not permitted to Department: " + department);
  }
 }

 /* Add the department you want to block */
 public List getProxyLock() {
  proxyLock.add("Math");
  proxyLock.add("Physics");
  proxyLock.add("Chemistry");
  // proxyLock.add("Biology");
  proxyLock.add("Psychology");
  proxyLock.add("Sociology");
  // proxyLock.add("Computer");
  // proxyLock.add("Accounts");
  return proxyLock;
 }
}


ProxyDesignPattern.java
package com.shubh.dp.example;

public class ProxyDesignPattern {
 public static void main(String[] args) {

  /* Access Internate without Proxy */
  // System.out.println("Access Internate without Proxy.");
  CollegeInternetImpl realObject = new CollegeInternetImpl("Math");
  realObject.getInternet();

  /* Access Internate using Proxy */
  // System.out.println("Access Internate using Proxy.");
  InternetProxy internet = new InternetProxy("Math");
  internet.getInternet();

  /* Access Internate using Proxy */
  // System.out.println("Access Internate using Proxy.");
  InternetProxy internetAcc = new InternetProxy("Accounts");
  internetAcc.getInternet();
 }
}

Output:

Internet has been connected successfully for Department: Math
Internet access not permitted to Department: Math
Internet has been connected successfully for Department: Accounts

Wednesday, April 24, 2019

Singleton pattern Vs Static Class

Q- What is the difference between singleton and static class in java
Answer: Singleton class Vs Static class


Singleton ClassStatic class
  Singleton class have only one object (an instance of the class)
  at a time per JVM. during application life cycle.
  Static class have all static member or methods.
  No need to instantiate stattic class. We can directly call methods of static class.
  StaticClassExample.getUserName();

  public class StaticClassExample {
          private static String userName = "Sumit";
          public static String getUserName(){
          return userName;
          }
   }
  Singleton class represent object.  Static class represent a static methods of a class.
  Singleton class and static class provides good accessibility and save memory.
  Singleton class methods are slower then Static methods.  Static methods are much faster  because of static binding during compile time.
  Singleton class is easy to test (unit testing)  Static classes are hard test (unit testing)
  Static class provides better performance than Singleton class,
  because static methods are bonded on compile time
  Singleton classes can be lazy loaded  Static class always eagerly loaded
  When To Use :
  Singleton class is used while interested to change state of property and single object      per JVM.
  Singleton maintaining state.
  Example :-  logging, caches, thread pools, configuration settings, device driver objects
  Static class or static methods are used while don't need to change state of property. OR used to create
    utility classes.
  Static does not maintaining any state.
  Example :- java.lang.Math, Apache StringUtils



6. Can we extends singleton class in java ?
Answer: NO
Because in singleton class have private constructor.
By default when you extend a class, Java will invoke the parent's no-arg constructor when constructing the subclass.


Related Tutorials

Tuesday, April 23, 2019

Singleton Class In Java

Q- What is singleton in java ?

Answer:- There should be only one instance allowed for the class in all the situation and we should provide global point of access to that instance.

Number of ways  to create singleton class :- 
  • Eager initialization or initialize before use
  • Lazy initialization or initialize as and when we need
  • Singleton using Inner class
  • Singleton with serialization and de serialization
  • Using Enum
  • A thread-safe singleton pattern in java using Synchronization
  • Double-checked locking
  • Double-checked locking with volatile keyword
  • Thread-safe but not lay initialized
  • The ultimate Thread-safe and efficient singleton pattern in Java 
Q- How to write singleton class in java ?
Answer :

Singleton.java
package design.patern.singleton;

public class Singleton {

 private static Singleton instance = null;
 
 // Constructor should be private
 private Singleton() {
 }

 // Create instance of class
 public static Singleton getInstance() {
  if (null == instance) {
   instance = new Singleton();
  }
  return instance;
 }

 public void demoMethod() {
  System.out.println("Print demoMethod");
 }

 public static void demoStaticMethod() {
  System.out.println("Print demoStaticMethod");
 }

}

SingletonMainClass.java
package design.patern.singleton;

public class SingletonMainClass {

 public static void main(String args[]) {
  Singleton inst = Singleton.getInstance();
  System.out.println(inst.hashCode());
  inst.demoMethod();
  Singleton.demoStaticMethod();
 }
}

Write Junit test cases for singletone class 
package design.patern.singleton;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Test;

public class SingletonClassTest {

 @Test
 public void testSingleton() {
  Singleton instance1 = Singleton.getInstance();
  Singleton instance2 = Singleton.getInstance();
  System.out.println("checking singleton objects equality");
  assertEquals(true, instance1 == instance2);
 }
}

  enum based singleton example 

While we create Singleton pattern using Enum, that in only one line of code and Enum instance is thread-safe and guaranteed by JVM. This is the most easy way of writing thread-safe Singleton in Java
public enum SingletonUsingEnum{
    INSTANCE;
}

Let's see complete example and how to use.
public enum SingletonUsingEnum {
    INSTANCE;
 
 private String name;

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }  
}

public class SingletonEnumTest {

 public static void main(String[] args) {

  SingletonUsingEnum singletone = SingletonUsingEnum.INSTANCE;
  singletone.setName("Amby");
  System.out.println(singletone.getName());

  SingletonUsingEnum singletone2 = SingletonUsingEnum.INSTANCE;
  System.out.println("singletone: " + singletone.hashCode() + "<======>singletone2: " + singletone2.hashCode());
  System.out.println("Is same singletone reference : " + singletone.equals(singletone2));
 }
}
Output: As we can see. I have created two instance of singleton but its return same hashCode() and also return true by using equal methods on two different reference.
Amby
singletone: 2018699554<======>singletone2: 2018699554
Is same singletone reference : true

Thread Safe Singleton in Java
package design.patern.singleton;

public class Singleton {

 private static Singleton instance = null;
 private static Object staticObject = new Object();

 // Constructor should be private
 private Singleton() {
 }

 // Create instance of class
 public static Singleton getInstance() {
  Singleton result = instance;
  if (result == null) {
   synchronized (staticObject) {
    result = instance;
    if (result == null)
     instance = result = new Singleton();
   }
  }
  return result;
 }

 public void demoMethod() {
  System.out.println("Print demoMethod");
 }

 public static void demoStaticMethod() {
  System.out.println("Print demoStaticMethod");
 }

}

Q- How to prevent Singleton Class from Serialization, Cloning and Reflection?
Answer:- Prevent Singleton Class from Serialization, Cloning and Reflection
To prevent using reflection we can trhow exception from constructor
              throw new IllegalArgumentException("Initialization through Reflection not allowed");
Q:- Singleton pattern Vs static class?
Answer:- Singleton pattern Vs static class

Question : Difference between singleton class and singleton scope in spring ? 

Spring Singleton Scope : Singleton in Spring guarantees to create only one bean instance for given bean per id definition per container.  that means if we define same bean with two id or name than two instance world be created. Spring Singletone Scope Example

Spring singleton pattern is different from gang of four singleton pattern. While gang of four Singleton pattern ensures that one and only one instance is created per ClassLoader.

Facade Pattern Java Example

Facade Design Pattern Java Example


Facade Pattern is a structural design pattern. its deals with interfaces, not implementation.
As the name suggests structural pattern is used to form a larger object structure from many different objects. Façade pattern is one such pattern which provides a simplified interface to a set of interfaces within a system and thus it hides the complexities of the subsystem from the client.
Facade Design Pattern hides the complexities of the system and provides an interface to the client from where the client can access the system.

The definition of Facade provided by Gang of Four book on Design Patterns states:
 Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.   

When To Use Facade Pattern :
The facade pattern is used when we have a complex system that we want to expose to clients in a simple way, or we want to make an external communication layer over an existing system which is incompatible with the system.
Facade deals with interfaces, not implementation. Its purpose is to hide internal complexity behind a single interface that appears simple on the outside.
Example : Suppose we have to generate report and we have two service to generate repote PDF or Excel. So we have to create one interface Report and its two implementation class ReportPDF and ReportExcel. So when user select either PDF or Excel so system will generate report of selected formate.












Related Tutorials

Strategy Pattern Java Example


Strategy pattern is a behavioral design pattern. Strategy pattern is use while we want to change the implementations of an algorithm at runtime, without causing tight coupling.

The definition of Strategy provided by Gang of Four book on Design Patterns states:
Defines a set of encapsulated algorithms that can be swapped to carry out a specific behavior.

Where Should We Use This Pattern?
If we have multiple algorithm for same task and we have to decide (let’s use decide) at run time. Which algorithm should be use?

Example:
Like compression algorithm we have different option to compress as file or folder such as ZIP, GZIP, LZ4, RAR, TAR, 7Z, GZ so hare user have choice whatever the format he can select at runtime.
Another example data encryption class that can encrypts data using different encryption algorithms, such as AES, Triple DES, and Blowfish.


EncryptorWithoutPertan.java
      
 package com.shubh.strategy.patern;

 public class EncryptorWithoutPertan {

 private String algoName;
 private String text;

 public void getEncryptedData() {
  if (algoName.equals("Aes")) { // using AES algorithm
   System.out.println("Output : " + text + " is Encrypted by AES algorithm");
  } else if (algoName.equals("Blowfish")) { // using Blowfish algorithm
   System.out.println("Output : " + text + " is Encrypted by Blowfish algorithm");
  }
 }

 public String getAlgoName() {
  return algoName;
 }

 public void setAlgoName(String algoName) {
  this.algoName = algoName;
 }

 public String getText() {
  return text;
 }

 public void setText(String text) {
  this.text = text;
 }
}
EncryptorMainTest.java
      
package com.shubh.strategy.patern;

public class EncryptorMainTest {

 public static void main(String[] args) {

  EncryptorWithoutPertan aseWP = new EncryptorWithoutPertan();
  aseWP.setAlgoName("Aes");
  aseWP.setText("Hello Data Test");
  aseWP.getEncryptedData();

  EncryptorWithoutPertan BlowfishWP = new EncryptorWithoutPertan();
  BlowfishWP.setAlgoName("Blowfish");
  BlowfishWP.setText("Hello Data Test");
  BlowfishWP.getEncryptedData();
 }
}
      
In the above code EncryptorWithoutPertan.java class we need to add if and else condition to implement the different algorithm. if we further want to add more algorithm then we need to modify this class.

Now Applying the Strategy Pattern :

EncryptionStrategyPattern.java
      
package com.shubh.strategy.patern;

public interface EncryptionStrategyPattern {

 public void getEncryptedData(String str);

}
      
Aes.java
package com.shubh.strategy.patern;

public class Aes implements EncryptionStrategyPattern {

 public void getEncryptedData(String str) {
  System.out.println("####### Encrypted data By AES algorithm #####");
  System.out.println("Output : " + str + " is Encrypted by AES algorithm");
 }
}

Blowfish.java

package com.shubh.strategy.patern;

public class Blowfish implements EncryptionStrategyPattern {

 public void getEncryptedData(String str) {
  System.out.println("####### Encrypted data By Blowfish algorithm #####");
  System.out.println("Output : " + str + " is Encrypted by Blowfish algorithm");
 }
}

EncryptorStrategyClass.java

package com.shubh.strategy.patern;

public class EncryptorStrategyClass {

 private EncryptionStrategyPattern strategy;
 private String text;

 public EncryptorStrategyClass(EncryptionStrategyPattern strategy) {
  this.strategy = strategy;
 }

 public void getEncryptedData() {
  strategy.getEncryptedData(text);
 }

 public String getText() {
  return text;
 }

 public void setText(String text) {
  this.text = text;
 }
}

Junit Test For StrategyPattern

EncryptorStrategyPatternTest.java

package com.shubh.strategy.patern;
import org.junit.Test;

public class EncryptorStrategyPatternTest {

 @Test
 public void getEncryptedDataTest() throws Exception {

  EncryptionStrategyPattern aes = new Aes();
  EncryptorStrategyClass aesEncryptor = new EncryptorStrategyClass(aes);
  aesEncryptor.setText("This is plain text");
  aesEncryptor.getEncryptedData();

  EncryptionStrategyPattern blowfishStrategy = new Blowfish();
  EncryptorStrategyClass blowfishEncryptor = new EncryptorStrategyClass(blowfishStrategy);
  blowfishEncryptor.setText("This is plain text");
  blowfishEncryptor.getEncryptedData();
 }
}

Note that using strategy pattern. I have create two seperate class Aes and  Blowfish to implement the two algorithm. if in future i need to add one more algorithm then i just need to add one more implementation class of   EncryptionStrategyPattern and no need to change in other class.

Template Method Design Pattern

Decorator Design Pattern

Q- How to write a decorator design pattern in java ?

The decorator pattern is a structural design pattern.
Decorator design pattern is used to add/enhance/modify the functionality of an object at run time without affect the functionality of existing object.
So that we don't need to modify existing class. it is the replacement of inheritance in java.
It is the replacement of inheritance.

The definition of Decorator pattern  provided by Gang of Four book on Design Patterns states:
Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

In the below code. I have book a room in a hotal and taken some services like news paper, bouquet etc. So this will manage billing for same.


Billing.java 

package com.shubh.design.patern.decorator;

public interface Billing {

 public int getTotalCost();

}


BillingImpl.java 

package com.shubh.design.patern.decorator;

public class BillingImpl implements Billing {

 public int getTotalCost() {
  System.out.println("Basis Cost: " + 100);
  return 100;
 }
}

BillingDecorator.java 

package com.shubh.design.patern.decorator;

public abstract class BillingDecorator implements Billing {

 protected Billing billingInstance;

 public BillingDecorator(Billing billingInstance) {
  this.billingInstance = billingInstance;
 }

 public int getTotalCost() {
  return billingInstance.getTotalCost();
 }
}

BouquetDecorator.java

package com.shubh.design.patern.decorator;

public class BouquetDecorator extends BillingDecorator {

 private Bouquet bouquet;

 public BouquetDecorator(Billing billingInstance, Bouquet bouquet) {
  super(billingInstance);
  this.bouquet = bouquet;
 }

 public int getTotalCost() {
  System.out.println("Bouquet(No. of days:" + bouquet.getNumberOfDay() + ", Cost Per day: "
    + bouquet.getCostPerBouquet() + ") Total Cost = " + getBouquetCost());
  return billingInstance.getTotalCost() + getBouquetCost();
 }

 public int getBouquetCost() {
  return bouquet.getNumberOfDay() * bouquet.getCostPerBouquet();
 }
}

class Bouquet {

 private int numberOfDay;
 private int costPerBouquet;

 public int getNumberOfDay() {
  return numberOfDay;
 }

 public void setNumberOfDay(int numberOfDay) {
  this.numberOfDay = numberOfDay;
 }

 public int getCostPerBouquet() {
  return costPerBouquet;
 }

 public void setCostPerBouquet(int costPerBouquet) {
  this.costPerBouquet = costPerBouquet;
 }
}

NewsPaparDecorator.java

package com.shubh.design.patern.decorator;

public class NewsPaparDecorator extends BillingDecorator {

 private NewsPapar newsPapar;

 public NewsPaparDecorator(Billing billingInstance, NewsPapar newsPapar) {
  super(billingInstance);
  this.newsPapar = newsPapar;

 }

 public int getTotalCost() {
  System.out.println("News Paper(No. of days :" + newsPapar.getNumberOfDay() + ", Cost Per day: "
    + newsPapar.getCostPerDay() + ") Total Cost = " + getNewsPaparCost());
  return billingInstance.getTotalCost() + getNewsPaparCost();
 }

 public int getNewsPaparCost() {
  return newsPapar.getNumberOfDay() * newsPapar.getCostPerDay();
 }
}

class NewsPapar {

 private int numberOfDay;
 private int costPerDay;

 public int getNumberOfDay() {
  return numberOfDay;
 }

 public void setNumberOfDay(int numberOfDay) {
  this.numberOfDay = numberOfDay;
 }

 public int getCostPerDay() {
  return costPerDay;
 }

 public void setCostPerDay(int costPerDay) {
  this.costPerDay = costPerDay;
 }
}


RoomChargeDecorator.java

package com.shubh.design.patern.decorator;

public class RoomChargeDecorator extends BillingDecorator {

 private Room room;

 public RoomChargeDecorator(Billing billingInstance, Room room) {
  super(billingInstance);
  this.room = room;
 }

 public int getTotalCost() {
  System.out.println("Room(No. of days:" + room.getNumberOfDay() + ", Charges Per day: "
    + room.getRoomChargePerDay() + ") Total Cost = " + getRoomCharges());
  return billingInstance.getTotalCost() + getRoomCharges();
 }

 public int getRoomCharges() {
  return room.getNumberOfDay() * room.getRoomChargePerDay();
 }
}

class Room {

 private int numberOfDay;
 private int roomChargePerDay;

 public int getNumberOfDay() {
  return numberOfDay;
 }

 public void setNumberOfDay(int numberOfDay) {
  this.numberOfDay = numberOfDay;
 }

 public int getRoomChargePerDay() {
  return roomChargePerDay;
 }

 public void setRoomChargePerDay(int roomChargePerDay) {
  this.roomChargePerDay = roomChargePerDay;
 }
}

BillingDecoratorMain.java 

package com.shubh.design.patern.decorator;

public class BillingDecoratorMain {

 public static void main(String[] args) {

  NewsPapar newsPaper = new NewsPapar();
  newsPaper.setNumberOfDay(5);
  newsPaper.setCostPerDay(2);

  Bouquet bouquet = new Bouquet();
  bouquet.setNumberOfDay(5);
  bouquet.setCostPerBouquet(150);

  Room room = new Room();
  room.setNumberOfDay(5);
  room.setRoomChargePerDay(1000);

  Billing billing = new NewsPaparDecorator(new BillingImpl(), newsPaper);
  billing = new BouquetDecorator(billing, bouquet);
  billing = new RoomChargeDecorator(billing, room);
  System.out.println("Net Cost To Pay = " + billing.getTotalCost());

 }

}

 
Advantage of Decorator design Pattern in Java.

  • The decorator pattern makes changes easier at run-time.
  • It reduces the number of combination classes.
  • More flexibility than inheritance.
  • In decorator design pattern, responsibilities can be added and removed at run-time
  • We can add any number of decorators in any order as per requirement.
  • It enhance the functionality of object without affecting any other object.

Disadvantage of Decorator design Pattern.

  • There are many number of files to be maintain.

Q- Decorator pattern Vs. Inheritance?
     Inheritance adds responsibility at compile time but decorator pattern adds at run time.

Q- Decorator Design Pattern – UML Diagram?

Q- When to use Decorator Design Pattern?

Example of decorator design patterns used in java API: 

  • java.io.BufferedReader
  • java.io.FileReader
  • java.io.Reader