Design Patterns mostly used
1. ) Creational
1.1) Singleton : One instance per jvm
Real life example(java) — java.lang.Runtime#getRuntime()
User A: Hey write a basic singleton class
public class SingletonExample{
private static SingletonExample singleton; // if initialize here then early loading
private SingletonExample(){
}
public static Singleton1 getInstance() {
if(singleton==null){ //lazy loading
singleton = new SingletonExample();
}
return singleton;
}
}
User A: Its not thread safe ?
User B : ok let me make method as synchronize
public class SingletonExample {
private static SingletonExample singleton; // if initialize here then early loading
private SingletonExample(){
}
public synchronized static SingletonExample getInstance() {
if(singleton==null){ //lazy loading
singleton = new SingletonExample();
}
return singleton;
}
}
User A : yeah !! Now its thread safe but there are performance issues with this approach bcoz only one thread can enter in this method to get Instance.
User B: ok let me add synchronised block(rather than method) and volatile to the instance.( double checked locking)
public class SingletonExample {
private volatile static SingletonExample singleton; // if initialize here then early loading
private SingletonExample(){
}
public SingletonExample getInstance() {
if(singleton==null){ //lazy loading
synchronized(this){
if(singleton==null)
singleton = new SingletonExample();
}
}
return singleton;
}
}
1.2) Factory method : Creates a family of object types.
Real life example (java) — java.util.Calendar#getInstance()
public interface Notification {
void notifyUser();
}
public class SMSNotification implements Notification {
@Override
public void notifyUser()
{
System.out.println("Sending an SMS notification");
}
}
public class EmailNotification implements Notification {
@Override
public void notifyUser()
{
System.out.println("Sending an e-mail notification");
}
}
//Factory method
public class NotificationFactory {
public Notification createNotification(String channel)
{
if (channel == null || channel.isEmpty())
return null;
switch (channel) {
case "SMS":
return new SMSNotification();
case "EMAIL":
return new EmailNotification();
default:
throw new IllegalArgumentException("Unknown channel "+channel);
}
}
}
/*Below we are passing notification type- SMS so , based on that
SMSNotification object will be created in Factory method
and thier notifyUser method will be called.
*/
public class NotificationService {
public static void main(String[] args)
{
NotificationFactory notificationFactory = new NotificationFactory();
Notification notification = notificationFactory.createNotification("SMS"); //here b
notification.notifyUser();
}
}
1.3 ) Builder Pattern :
It is a creational design pattern that lets you construct complex objects step by step. It allows you to produce different types and representations of a product using the same construction code. However, this pattern should be used only if you need to build different immutable objects using the same building process.
Real life example(java) — java.lang.StringBuilder & lombok annotation @Builder to create object instance.
Below example can have different variations to write builder for any particular class.
public class Book {
private final String isbn;
private final String title;
private final String author;
private final Year published;
private final String description;
private Book(Builder builder) {
this.isbn = builder.isbn;
this.title = builder.title;
this.author = builder.author;
this.published = builder.published;
this.description = builder.description;
}
//Gettters & Setters
public static class Builder {
private final String isbn;
private final String title;
private String author;
private Year published;
private String description;
public Builder(String isbn, String title) {
this.isbn = isbn;
this.title = title;
}
public Builder author(String author) {
this.author = author;
return this;
}
public Builder published(Year published) {
this.published = published;
return this;
}
public Builder description(String description) {
this.description = description;
return this;
}
public Book build() {
return new Book(this);
}
}
}
/* Now create object by Builder pattern
- Here isbn & Title as mandatory so passing in constuctor of Builder
and others are optional fields to create object.
*/
Book book = new Book.Builder("0-12-345678-9", "Moby-Dick")
.author("Herman Melville")
.published(Year.of(1851))
.description(
"The book is the sailor Ishmael's narrative of the obsessive quest of "
+ "Ahab, captain of the whaling ship Pequod, for revenge on Moby Dick, "
+ "the giant white sperm whale that on the ship's previous voyage bit "
+ "off Ahab's leg at the knee."
)
.build();
References :
https://dzone.com/articles/demystifying-volatile-and-synchronized-again