How it Works

  1. We have JSON file with Location and Name of Factory Class
  2. Using Configuration.java we read the JSON File and read the Configuration
  3. We run TasteFoodFromMenu.java by supplying the JSON file Location as Input
  4. Now by the above method the JAR’s could be built independently and by changing the JSON file we could make changes and deploy the code without restarting the Server

For more detail refer here

Configuration.java

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;

import com.fasterxml.jackson.databind.ObjectMapper;

public class Configuration {

    public static Configuration loadConfiguration(String fileName) throws IOException {    	
    	//Read Name of File
        Path path = FileSystems.getDefault().getPath(fileName);
        
        //Read Contents of File
        String contents = new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
        
        ObjectMapper mapper = new ObjectMapper();
        
        //Map Location and FactoryType
        Configuration config = mapper.readValue(contents, Configuration.class);
        return config;
    }

    private String factoryType;
    private String location;


    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public String getFactoryType() {
        return factoryType;
    }

    public void setFactoryType(String factoryType) {
        this.factoryType = factoryType;
    }
}

TasteFoodFromMenu.java

public class TasteFoodFromMenu {
	  public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException {
	        Configuration configuration = Configuration.loadConfiguration(args[0]);
	        String location = configuration.getLocation();
	        URL url = new URL(location);
	        URLClassLoader ucl = new URLClassLoader(new URL[]{url});
	        Class<IFoodFactory> cls = (Class<IFoodFactory>) Class.forName(configuration.getFactoryType(), true, ucl);
	        IFoodFactory cameraFactory = cls.newInstance();
	        IFood camera = cameraFactory.prepareFood(); 
	        camera.serveFood();
	    }
}

config.json

{
  "factoryType": "com.mugil.food.ChineseFoodFactory",
  "location": "file:///D:/java/ReadConfFromJSON/lib/FoodMenu.jar"
}

Abstract Factory Pattern
The Abstract Factory Pattern consists of an AbstractFactory, ConcreteFactory, AbstractProduct, ConcreteProduct and Client. We code against AbstractFactory and AbstractProduct and let the implementation to others to define ConcreteFactory and ConcreteProduct

IFoodFactory.java(AbstractFactory)

public interface IFoodFactory {
	public IFood prepareFood();
}

IFood.java(AbstractProduct)

public interface IFood {
	public void serveFood();
}

ItalianFoodFactory.java(ConcreteFactory)

public class ItalianFoodFactory implements IFoodFactory{
	@Override
	public IFood prepareFood() {
		return new ItalianFood();
	}
}

ChineseFoodFactory.java(ConcreteFactory)

public class ChineseFoodFactory implements IFoodFactory{
	@Override
	public IFood prepareFood() {
		return new ChineseFood();
	}
}

ItalianFood.java(ConcreteProduct )

public class ItalianFood implements IFood{
	@Override
	public void serveFood() {
	  System.out.println("Pepperoni Pizza by Sam");		
	}
}

ChineseFood.java(ConcreteProduct )

public class ChineseFood implements IFood{
	@Override
	public void serveFood() {
		System.out.println("Snake Soup by Bruce");;
	}		
}

TasteFood.java(Client)

public class TasteFood {
	public static void main(String[] args) {
		IFoodFactory objFoodFactory = new ChineseFoodFactory();
		IFood objFood = objFoodFactory.prepareFood();		
		objFood.serveFood();
	}
}

Output

Snake Soup by Bruce

With the Factory pattern, you produce instances of implementations (ChineseFood, ItalianFood, ThaiFood, etc.) of a particular interface — say, IFood.
With the Abstract Factory pattern, you provide a way for anyone to provide their own factory. This allows your warehouse to be either an IFoodFactory or an IJuiceFactory, without requiring your warehouse to know anything about Food or Juices.Abstract Factory pattern, a class delegates the responsibility of object instantiation to another object via composition whereas the Factory Method pattern uses inheritance and relies on a subclass to handle the desired object instantiation.

Factory Pattern Abstract Factory pattern
Factory Method creates objects through inheritance Abstract Factory creates objects through composition
Factory Method pattern is responsible for creating products that belong to one family Abstract Factory pattern deals with multiple families of products i.e. Food, Juice, Dessert
Factory Method uses interfaces and abstract classes to decouple the client from the generator class and the resulting products Abstract Factory has a generator that is a container for several factory methods, along with interfaces decoupling the client from the generator and the products

Download example of Abstract Factory pattern from here

In a Application the persistence unit used to store the data may vary.Accessing data varies depending on the source of the data. Access to persistent data varies greatly depending on the type of storage (database, flat files, xml files, and so on) and it even differs from its implementation (for example different SQL-dialects).

The advantage of the DAO layer is that if you need to change the underlying persistence mechanism you only have to change the DAO layer, and not all the places in the domain logic where the DAO layer is used from. The DAO layer usually consists of a smaller set of classes, than the number of domain logic classes that uses it.

Abstract and encapsulate all access to the data and provide an interface. This is called the Data Access Object pattern. In a nutshell, the DAO “knows” which data source (that could be a database, a flat file or even a WebService) to connect to and is specific for this data source (e.g. a OracleDAO might use oracle-specific data types, a WebServiceDAO might parse the incoming and outgoing message etc.)

BookDAO.java

public interface BookDAO {
  public void saveBook(Book b);
  public Book loadBook(String isbn);
}

DBBookDAO.java

public class DBBookDAO implements BookDAO {

  private PreparedStatement saveStmt;
  private PreparedStatement loadStmt;

  public DBBookDAO(String url, String user, String pw) {
    Connection con = DriverManager.getConnection(url, user, pw);
    saveStmt = con.prepareStatement("INSERT INTO books(isbn, title, author) "
                                   +"VALUES (?, ?, ?)");
    loadStmt = con.prepareStatement("SELECT isbn, title, author FROM books "
                                   +"WHERE isbn = ?");
  }

  public Book loadBook(String isbn) {
    Book b = new Book();
    loadStmt.setString(1, isbn);
    ResultSet result = loadStmt.executeQuery();
    if (!result.next()) return null;
    
    b.setIsbn(result.getString("isbn"));
    b.setTitle(result.getString("title"));
    b.setAuthor(result.getString("author"));
    return b;
  }

  public void saveBook(Book b) {
    saveStmt.setString(1, b.getIsbn());
    saveStmt.setString(2, b.getTitle());
    saveStmt.setString(3, b.getAuthor());
    saveStmt.executeUpdate();
  }
}

FileBookDAO.java

public class FileBookDAO implements BookDAO {
        
  private String basePath;

  public FileBookDAO(String basePath) {
    this.basePath = basePath;
  }

  public Book loadBook(String isbn) {
    FileReader fr = new FileReader(basePath + isbn);
    BufferedReader br = new BufferedReader(fr);
    Book b = new Book();
    String rIsbn = br.readLine();
    String rTitle = br.readLine();
    String rAuthor = br.readLine();
        
    if (rIsbn.startsWith("ISBN: ")) {
      b.setIsbn(rIsbn.substring("ISBN: ".length()));
    } else {
      return null;
    }
    if (rTitle.startsWith("TITLE: ")) {
      b.setTitle(rTitle.substring("TITLE: ".length()));
    } else {
      return null;
    }
    if (rAuthor.startsWith("AUTHOR: ")) {
      b.setAuthor(rAuthor.substring("AUTHOR: ".length()));
    } else {
      return null;
    }
    return b;
  }

  public void saveBook(Book b) {
    FileWriter fw = new FileWriter(basePath + b.getIsbn() + ".book");
    fw.write("ISBN: " + b.getIsbn());
    fw.write("TITLE: " + b.getTitle());
    fw.write("AUTHOR: " + b.getAuthor());
    fw.close();
  }
}

Lets take the below scenario where there are Different segment of customers whose discount rates is going to vary based on the segment type and the Store they are visiting

Now the Customer may hold Platinum,Premium or Club Card which avails them some discount on the total bill amount.
Again this discount vary based on the store from which the purchase is made Regular, Franchise, Licensed Store

Visitor.java

package com.mugil.visitor;

public interface Visitor {
	public double getDiscount(FranchiseStore objFranchiseStore);
	public double getDiscount(RegularStore objRegularStore);
	public double getDiscount(LicensedStore objLicensedStore);
}

Visitable.java

package com.mugil.visitor;

public interface Visitable {
	public double acceptDiscount(Visitor objVisitior);	
}

FranchiseStore.java

package com.mugil.visitor;

public class FranchiseStore implements Visitable{
	private int totalBillAmt;

	FranchiseStore(int item) {
		totalBillAmt = item;
	}

	public int getTotalBillAmt() {
		return totalBillAmt;
	}

	@Override
	public double acceptDiscount(Visitor objVisitior) {
		// TODO Auto-generated method stub
		return 0;
	}		
}

RegularStore.java

package com.mugil.visitor;

public class RegularStore implements Visitable {

	private int totalBillAmt;

	RegularStore(int item) {
		totalBillAmt = item;
	}

	public double acceptDiscount(Visitor visitor) {
		return visitor.getDiscount(this);
	}

	public double getTotalBillAmt() {
		return totalBillAmt;
	}		
}

LicensedStore.java

package com.mugil.visitor;

public class LicensedStore implements Visitable {
	
	private int totalBillAmt;

	LicensedStore(int item) {
		totalBillAmt = item;
	}

	public double acceptDiscount(Visitor visitor) {
		return visitor.getDiscount(this);
	}

	public double getTotalBillAmt() {
		return totalBillAmt;
	}

}

ClubCardVisitor.java

package com.mugil.visitor;

public class ClubCardVisitor implements Visitor 
{	
	@Override
	public double getDiscount(FranchiseStore objFranchiseStore) {
		// TODO Auto-generated method stub
		return 0.02;	
	}

	@Override
	public double getDiscount(RegularStore objRegularStore) {
		// TODO Auto-generated method stub
		return 0.03;
	}

	@Override
	public double getDiscount(LicensedStore objLicensedStore) {
		// TODO Auto-generated method stub
		return 0.00;
	}
}

PlatinumCardVisitor.java

package com.mugil.visitor;

public class PlatinumCardVisitor implements Visitor 
{
	@Override
	public double getDiscount(FranchiseStore objFranchiseStore) {
		// TODO Auto-generated method stub
		return 0.05;
	}

	@Override
	public double getDiscount(RegularStore objRegularStore) {
		// TODO Auto-generated method stub
		return 0.07;
	}

	@Override
	public double getDiscount(LicensedStore objLicensedStore) {
		// TODO Auto-generated method stub
		return 0.03;
	}

}

PremiumCardVisitor.java

package com.mugil.visitor;

public class PremiumCardVisitor implements Visitor {
	@Override
	public double getDiscount(FranchiseStore objFranchiseStore) {
		// TODO Auto-generated method stub
		return 0.03;
	}

	@Override
	public double getDiscount(RegularStore objRegularStore) {
		// TODO Auto-generated method stub
		return 0.05;
	}

	@Override
	public double getDiscount(LicensedStore objLicensedStore) {
		// TODO Auto-generated method stub
		return 0.02;
	}
}

GetVisitorDiscount.java

package com.mugil.visitor;

public class GetVisitorDiscount 
{
	public static void main(String[] args) 
	{		
		int totalBillAmount = 500;
		
		System.out.println("Discount for Club Card Visitor @ Franchise Store");
		
		ClubCardVisitor objClubCardVisitor = new ClubCardVisitor();
		FranchiseStore objFranchiseStore = new FranchiseStore(totalBillAmount);
		
		
		double discountPct = objClubCardVisitor.getDiscount(objFranchiseStore);
		double discountAmt = objClubCardVisitor.getDiscount(objFranchiseStore)*totalBillAmount;
		double AmtAfterDis = totalBillAmount - discountAmt; 
		
		
		System.out.println("---------------------------------------------------");
		System.out.println("Total Amount of Purchase " + totalBillAmount);
		System.out.println("Discount Percentage " + discountPct*100 + "%");
		System.out.println("Discount Amount " + discountAmt);
		System.out.println("Total Amount after Discount " + AmtAfterDis);
	}
}

Output

Discount for Club Card Visitor @ Franchise Store
---------------------------------------------------
Total Amount of Purchase 500
Discount Percentage 2.0%
Discount Amount 10.0
Total Amount after Discount 490.0

Singleton.java

public class Singleton 
{ 
    private static Singleton instance;   
 
    private Singleton() {}

    public static Singleton getInstance() 
    {
       if (instance == null) {
          instance = new Singleton();
       }
       return instance;
    }
}

In a Multi-threaded Environment

  1. Two Threads, Thread A and Thread B tries to access Object of Singleton class
  2. Thread A and B does call to Static getInstance() method
  3. Now when Thread A tries to do Null Check of instance instance == null chances of Thread B also entered the if block exists
    .
    .
    .
    if (instance == null) 
    {
      //Two threads may have passed the condition and might have got in
      instance = new Singleton();
    }
    .
    .
    .
    
  4. Now both the Threads have their own instance for the Singleton class.
  5. So there would be 2 instances of Singleton class at the end of if Block

Now there are two work around’s

Method 1
In this method we does static block initialization of Singleton along with synchronized getInstance() method which allows the access to only one thread at a point of time.
Singleton.java

public class Singleton 
{
    private static Singleton instance;
 
    private Singleton() {}

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

But the above method is expensive since there is unnecessary locking and unlocking done every time the object get accessed.

Method 2(Double Checked Locking Singleton)
Instead of synchronizing the whole method lets synchronize the block of code which allows single thread to access the instance during the first time access.The consecutive thread would be served with the same thread allocated for the First thread once it is done with its task.

Singleton.java

public class Singleton 
{
    private volatile static Singleton instance;

    private Singleton() {}

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

Other ways of achieving singleton are by using Eager Initialization and ENUM which has its own advantages and disadvantages.

In which scenario we should serialize a singleton?
Imagine you have a long-running app and want to be able to shut it down and later continue at the point where it was shut down (e.g. in order to do hardware maintenance). If the app uses a singleton that is stateful, you’d have to be able to save and restore the sigleton’s state, which is most easily done by serializing it.

Is it possible to serialize a singleton object?
2 Methods

  1. By using ENUM : ENUM implements Serializable by Default
  2. By adding implements Serializable to class to make it serializable, and delaring all instance fields transient (to prevent a serialization attack) and provide a readResolve method.

readResolve() method in Singleton Class implementing Serialization

.
.
// readResolve method to preserve singleton property
private Object readResolve() {
     // Return the one true Elvis and let the garbage collector
     // take care of the Elvis impersonator.
    return INSTANCE;
}
.
.

Why you need readResolve() Method
This method will be invoked when you will de-serialize the object. Inside this method, you must return the existing instance to ensure single instance application wide.

The Way serialization works is as below

Serializes the Object Property -> Stores to Persistent Storage
From Persistent Storage -> Creates new Object and Sets Properties of Object

The Object Before Serialization and after Serialization are not same. Only the Object Properties are same

Now lets take a simple Example where we serializes the PrintReport Class which has priority as one of its Object Variable.priority tells which should be given first preference while printing

PrintReport.java

package com.mugil.org;

import java.io.Serializable;

public class PrintReport implements Serializable {
    private static PrintReport instance = null;
	 
    public static PrintReport getInstance() {
        if (instance == null) {
            instance = new PrintReport();
        }
        return instance;
    }
    
    private transient int priority = 2;

	public int getPriority() {
		return priority;
	}
	
	public void setPriority(int priority) {
		this.priority = priority;
	}
}

Now when the above singleton which implements serialization gets called as below

PrintMedicalReport.java

package com.mugil.org;

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

public class PrintMedicalReport 
{	
	 static PrintReport instanceOne = PrintReport.getInstance();
	 
	    public static void main(String[] args) {
	        try {
	            // Serialize to a file
	            ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
	                    "filename.ser"));
	            out.writeObject(instanceOne);
	            out.close();
	            
	            instanceOne.setPriority(1);
	            
	            // Serialize to a file
	            ObjectInput in = new ObjectInputStream(new FileInputStream(
	                    "filename.ser"));
	            PrintReport instanceTwo = (PrintReport) in.readObject();
	            in.close();
	 
	            System.out.println(instanceOne.getPriority());
	            System.out.println(instanceTwo.getPriority());
	 
	        } catch (IOException e) {
	            e.printStackTrace();
	        } catch (ClassNotFoundException e) {
	            e.printStackTrace();
	        }
	    }
}

Output

1
2

Note in the above code the instanceOne.setPriority(2); should have been called before out.writeObject(instanceOne).But that is not the case since the example explains the Object are different before and after Serialization.Only Object Properties(Metadata) are stored during serialization not the actual object.

You can see the Class Prints default Priority value in the output.

Now in context to singleton we want to maintain exactly one Object exist before and after serialization. Not with two object with same set of attributes.To achieve this we add readResolve() Method.

PrintReport.java

package com.mugil.org;

import java.io.Serializable;

public class PrintReport implements Serializable {
	private volatile static PrintReport instance = null;
	 
    public static PrintReport getInstance() {
        if (instance == null) {
            instance = new PrintReport();
        }
        return instance;
    }
    
    private int priority = 1;

	public int getPriority() {
		return priority;
	}
	
	public void setPriority(int priority) {
		this.priority = priority;
	}    
	     
    protected Object readResolve() {
        return instance;
    }   
}

Now when the PrintMedicalReport class gets executed the Output would be as below

Output

1
1

When you Serialize and Deserialize new file would be created and stored in disk every time.

In the above image by changing the filename.ser text you can change the attribute of objects serialized. This is known as Serialization attack. To overcome this you must declare all instance fields as transient.

Reference 2

Lets Consider the below Singleton code which uses Double Checked Locking

DoubleCheckLocking.java

public class DoubleCheckLocking 
{
    public static class SearchBox 
    {
        private static volatile SearchBox searchBox;

        //Private constructor
        private SearchBox() {}

        //Static method to get instance
        public static SearchBox getInstance() {
            if (searchBox == null) { // first time lock
                synchronized (SearchBox.class) {
                    if (searchBox == null) {  // second time lock
                        searchBox = new SearchBox();
                    }
                }
            }
            return searchBox;
        }
}

Lets dive deep into the code where Double Checking actually takes place

  if (searchBox == null) { // first time lock
                synchronized (SearchBox.class) {
                    if (searchBox == null) {  // second time lock
                        searchBox = new SearchBox();
                    }
                }
            }
  1. Lets say we have two threads A and B and lets assume that atleast one of them reaches line 3 and observes searchBox == null is true.
  2. Two threads can not both be at line 3 at the same time because of the synchronized block. This is the key to understanding why double-checked locking works.
  3. So, it must the case that either A or B made it through synchronized first. Without loss of generality, say that that thread is A. Then, upon seeing searchBox == null is true, it will enter the body of the statement, and set searchBox to a new instance of SearchBox. It will then eventually exit the synchronized block.
  4. Now it will be B’s turn to enter: remember, B was blocked waiting for A to exit. Now when it enters the block, it will observe searchBox. But A will have left just having set searchBox to a non-null value.

Simple Singleton Using ENUM

MySingleton.java

public enum MySingleton {
  INSTANCE;   
}

Enum Classes has Private Constructor by Default

The Above code can be explicitly written as

MySingleton.java

public enum MySingleton {
    public final static MySingleton INSTANCE = new MySingleton();
    private MySingleton() {
    }
}

When your code first accesses INSTANCE, the class MySingleton will be loaded and initialized by the JVM. This process initializes the static field above once (lazily).

Why cant enum constructors be protected or public in Java?
Enums as a class with a finite number of instances. There can never be any different instances beside the ones you initially declare.Thus, you cannot have a public or protected constructor, because that would allow more instances to be created.

  1. Eager initialization
  2. Lazy initialization
  3. Static block initialization
  4. Thread Safe Singleton
  5. Thread Safe Singleton – Double Checked Locking
  6. Enum Singleton

Eager initialization
instance of Singleton Class is created at the time of class loading

EagerInitialized.java

package com.mugil.singleton;

public class EagerInitialized {
	
	private static final EagerInitialized instance = new EagerInitialized();
	
	//Private Constructor
	private EagerInitialized()
	{
		
	}
	
	public static EagerInitialized getInstance()
	{
        return instance;
    }	
}

Lazy Initialization
With lazy initialization you crate instance only when its needed and not when the class is loaded

LazyInitialized.java

package com.mugil.singleton;

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

Static Block Initialization
Static block initialization implementation is similar to eager initialization, except that instance of class is created in the static block that provides option for exception handling.

StaticBlockInitialized.java

package com.mugil.singleton;

public class StaticBlockInitialized {

	private static StaticBlockInitialized instance;

	private StaticBlockInitialized() {

	}

	// Static block initialization for exception handling
	static {
		try {
			instance = new StaticBlockInitialized();
		} catch (Exception e) {
			throw new RuntimeException("Exception occured in creating singleton instance");
		}
	}

	public static StaticBlockInitialized getInstance() {
		return instance;
	}
}

Thread Safe Singleton
The easier way to create a thread-safe singleton class is to make the access method synchronized, so that only one thread can execute this method at a time.

ThreadSafeSing.java

package com.mugil.singleton;

public class ThreadSafeSing {

    private static ThreadSafeSinginstance;
    
    private ThreadSafeSing(){}
    
    public static synchronized ThreadSafeSing getInstance(){
        if(instance == null){
            instance = new ThreadSafeSing();
        }
        return instance;
    }    
}

Double Checked Locking Singleton
Above Implementation of Singleton provides thread safety buy has a hit over performance.Refer the link for the same Link

In the Below method of Implementing Singleton, Synchronized Block is used rather than Synchronized Method.
DCCSingleton.java

package com.mugil.singleton;

public class DCCSingleton{

    private static DCCSingletoninstance;
    
    private DCCSingleton(){}
    
   public static DCCSingleton getInstanceUsingDoubleLocking()
   {
    if(instance == null){
        synchronized (DCCSingleton.class) {
            if(instance == null){
                instance = new DCCSingleton();
            }
        }
    }
    return instance;
  }    
}

Refer the Link for how Double Checked Locking works

ENUM Singleton
ENUMSingleton.java
Simple Singleton using enum for DBConnection

enum Singleton
{
    INSTANCE;

    // instance vars, constructor
    private final Connection connection;

    private Singleton()
    {
        //Initialize the connection
        connection = DB.getConnection();
    }

    // Static getter
    public static Singleton getInstance()
    {
        return INSTANCE;
    }

    public Connection getConnection()
    {
        return connection;
    }

The Connection can be created using the Below Code

Connection Conn = Singleton.getInstance().getConnection();
Eager Initialization Lazy Initialization Static Block Initialization Thread Safe Singleton
Object Gets Created once the Class is Loaded Object is Created once required Object is Created once Static Block is loaded Object is Created when requested by Thread
In lazy initialization you give a public API to get the instance. In multi-threaded environment it poses challenges to avoid unnecessary object creation Provides Option to Exception Handling Thread safety is guaranteed.Slow performance because of locking overhead

Advantages

  1. You escape the unnecessary object creation

Disadvantage

  1. In lazy initialization you give a public API to get the instance. In multi-threaded environment it poses challenges to avoid unnecessary object creation

A singleton pattern ensures that you always get back the same instance of whatever type you are retrieving, whereas the factory pattern generally gives you a different instance of each type.

The purpose of the singleton is where you want all calls to go through the same instance. An example of this might be a class that manages a disk cache, or gets data from a static dictionary; wherever it is important only one known instance interacts with the resource. This does make it less scalable.

The purpose of the factory is to create and return new instances. Often, these won’t actually be the same type at all, but they will be implementations of the same base class. However, there may be many instances of each type