1. In Simple Factory we have a Factory Class(LoggerFactory.java) and We call the createLogger method which returns different implementation of logger
  2. Logger is a abstract class which has different implementations

Logger.java

public abstract class Logger {
  abstract void log(String logstring);
}

ConsoleLogger.java

public class ConsoleLogger extends Logger{
    @Override
    void log(String logstring) {
        System.out.println("Logging to Console - "+ logstring);
    }
}

DBLogger.java

public class DBLogger extends Logger{
    @Override
    void log(String logstring) {
        System.out.println("Logging to Database - "+ logstring);
    }
}

FileLogger.java

public class FileLogger extends Logger{
    @Override
    void log(String logstring) {
        System.out.println("Logging to File - "+ logstring);
    }
}

LoggerFactory.java

public class LoggerFactory {
    public enum LoggerType {
        DATABASE, FILE, CONSOLE;
    }

    //The same code could be written using if else block instead of switch case
    public Logger createLogger(LoggerType loggerType) {
        Logger logger;

        switch (loggerType) {
            case FILE:
                logger = new FileLogger();
                break;
            case DATABASE:
                logger = new DBLogger();
                break;
            case CONSOLE:
                logger = new ConsoleLogger();
                break;
            default:
                logger = new ConsoleLogger();
                break;
        }

        return logger;
    }
}

ClientApp.java

public class ClientApp {
    public static void main(String[] args) {
        LoggerFactory objLoggerFactory = new LoggerFactory();
        Logger logger = objLoggerFactory.createLogger(LoggerFactory.LoggerType.CONSOLE);
        logger.log("Hello there");
    }
}

Output

Logging to Console - Hello there

Factory allows the consumer to create new objects without having to know the details of how they’re created, or what their dependencies are – they only have to give the information they actually want.

Account.java

abstract class Account {
   abstract Integer calculateInterest();
}

CreditAccount.java

public class CreditAccount extends Account{
    @Override
    Integer calculateInterest() {
        return 11;
    }
}

SalaryAccount.java

public class SalaryAccount extends Account{
    @Override
    Integer calculateInterest() {
        return 5;
    }
}

SavingsAccount.java

public class SavingsAccount extends Account{
   @Override
    Integer calculateInterest() {
        return 7;
    }
}

AccountFactory.java

public class AccountFactory {
    static Map<String, Account>  hmAccountMap =  new HashMap<>();

    static {
        hmAccountMap.put("SavingsAcc", new SavingsAccount());
        hmAccountMap.put("CreditAcc", new CreditAccount());
        hmAccountMap.put("SalaryAcc", new SalaryAccount());
    }

    public static Account getAccount(String accountType){
        return hmAccountMap.get(accountType);
    }
}

CalcInterest.java

public class CalcInterest{
    public static void main(String[] args) {
        Account objAccountFactory = AccountFactory.getAccount("SavingsAcc");
        System.out.println("Interest rate is - " + Optional.of(objAccountFactory.calculateInterest()));
    }
}

Using Streams for AccountFactory Class
AccountFactory.java

public static Optional<Account> getAccount(String accountType) {
        return hmAccountMap.entrySet().stream()
                                      .filter(accParam -> accParam.getKey().equals(accountType))
                                      .findFirst()
                                      .map(Map.Entry::getValue);
}

CalcInterest.java

public class CalcInterest{
    public static void main(String[] args) {
        Account objAccountFactory = AccountFactory.getAccount("SavingsAcc");
        System.out.println("Interest rate is - " + Optional.of(objAccountFactory.calculateInterest()));
    }
}

Output

Interest rate is - 7

Static factory method is a static method that returns an instance of a class. The key idea is to gain control over object creation and delegate it from constructor to static method.

The key idea of static factory method is to gain control over object creation and delegate it from constructor to static method. The decision of object to be created is like in Factory made outside the method (in common case, but not always). While the key (!) idea of Factory Method is to delegate decision of what instance of class to create inside Factory Method. E.g. classic Singleton implementation is a special case of static factory method. Example of commonly used static factory methods:

  • valueOf
  • getInstance(used in singleton)
  • newInstance

When to use?

  1. Static factory methods can have meaningful names, hence explicitly conveying what they do
  2. Static factory methods can return the same type that implements the method(s), a subtype, and also primitives, so they offer a more flexible range of returning types
  3. Static factory methods can encapsulate all the logic required for pre-constructing fully initialized instances, so they can be used for moving this additional logic out of constructors. This prevents constructors from performing further tasks, others than just initializing fields

Another example of static factory is as follow

Optional<String> value1 = Optional.empty();
Optional<String> value2 = Optional.of("Baeldung");
Optional<String> value3 = Optional.ofNullable(null);

Logger.java

public class Logger {
    public String logType;
    public String fileLocation;

    public Logger(String logType) {
        this.logType = logType;
    }

    public Logger() {
    }

    public static Logger getDefaultLogger(){
        return new Logger("Console");
    }

    public static Logger getFileLogger(String fileLocation){
        Logger logger =  new Logger("File");
        logger.fileLocation = fileLocation;
        return logger;
    }

    @Override
    public String toString() {
        return "Logger{" +
                "logType=" + logType +
                ", fileLocation='" + fileLocation + '\'' +
                '}';
    }
}

ClientApp.java

public class ClientApp {
    public static void main(String[] args) {
        Logger objLogger = Logger.getDefaultLogger();
        System.out.println(objLogger);
    }
}

Output

Logger{logType=Console, fileLocation='null'}

Logger.java

public class Logger {
    public String logType;
    public String fileLocation;

    public Logger(String logType) {
        this.logType = logType;
    }

    public Logger() {
    }

    public static Logger getLoggerInstance(LoggerType loggerType){
        Logger logger;
        switch(loggerType) {
            case CONSOLE:
                logger = new Logger("Console Logger");
                logger.fileLocation = "JVM Memory";
                break;
            case DATABASE:
                logger = new Logger("Database Logger");
                logger.fileLocation = "DB Connection";
                break;
            case FILE:
                logger = new Logger("File Logger");
                logger.fileLocation = "C:/logs";
                break;
            case SPLUNK:
                logger = new Logger("Splunk Logger");
                logger.fileLocation = "Splunk URL";
                break;
            default:
                logger = new Logger();

        }

        return logger;
    }

    @Override
    public String toString() {
        return "Logger{" +
                "logType=" + logType +
                ", fileLocation='" + fileLocation + '\'' +
                '}';
    }
}

ClientApp.java

public static void main(String[] args) {
        Logger objLogger = Logger.getLoggerInstance(LoggerType.CONSOLE);
        System.out.println(objLogger);
    }

LoggerType.java

public enum LoggerType {
    CONSOLE, FILE, DATABASE, SPLUNK
}

Output

Logger{logType=Console Logger, fileLocation='JVM Memory'}

Simple Factory and Static Factory are not design patterns rather coding style. However factory pattern could be implemented by using any one of the coding style but they wont honor Open Closed Principle.

As per Open Closed Principle, Code should be open to extension and Closed to Changes. In both the above coding style we have to change either the if else or switch case if new implementation of abstract class is introduces.

Factory Pattern is a design pattern in object-oriented programming that lets subclasses decide which class to instantiate when creating an object

Now Factory pattern honors Open Closed Principle and does not need change to factory method

Factory Pattern vs Abstract Factory Pattern
One difference between the two is that with the 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

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

Why Abstract Factory Introduced?
Another layer of abstraction over factory pattern. Abstract Factory patterns work around a super-factory which creates other factories. Factory pattern deals with creating objects of a single type(AppleFactory manufactures Iphones), while the Abstract Factory pattern deals with creating objects of related types(MobileFactory manufactures Mobiles). Abstract Factory pattern is more robust and consistent and uses composition to delegate responsibility of object creation.

When to use Abstract Factory?
When higher level of Abstraction is required.Provides an interface for creating families of related objects

MobileManufactureFactory.java

public interface MobileManufactureFactory {
    public Mobiles getManufacturerDetails();
}

Mobiles.java

public interface Mobiles {
    public void getMobileModels();
}

AppleFactory.java

public class AppleFactory implements MobileManufactureFactory {
    @Override
    public Mobiles getManufacturerDetails() {
        return new Iphone();
    }
}

GoogleFactory.java

public class GoogleFactory implements MobileManufactureFactory {
    @Override
    public Mobiles getManufacturerDetails() {
        return new Android();
    }
}

MicrosoftFactory.java

public class MicrosoftFactory implements MobileManufactureFactory {
    @Override
    public Mobiles getManufacturerDetails() {
        return new Windows();
    }
}

IphoneMobiles.java

public class IphoneMobiles implements Mobiles {
    @Override
    public void getMobileModels() {
        System.out.println("Iphone 13,14 and 15");
    }
}

AndroidMobiles.java

public class AndroidMobiles implements Mobiles {
    @Override
    public void getMobileModels() {
        System.out.println("Oneplus, Realme, Samsung");
    }
}

WindowsMobile.java

public class WindowsMobile implements Mobiles {
    @Override
    public void getMobileModels() {
        System.out.println("Samsung Focus, Nokia Lumia, Pocket PC");
    }
}

MobileFactory.java

public class MobileFactory {
    private MobileFactory(){
    }

    public static MobileManufactureFactory getMobilesBasedOnManufacturer(MobileCompany manufacturerName){
        if(manufacturerName.equals(MobileCompany.APPLE)){
            return new AppleFactory();
        }else if(manufacturerName.equals(MobileCompany.MICROSOFT)){
            return new MicrosoftFactory();
        }else if(manufacturerName.equals(MobileCompany.GOOGLE)){
            return new GoogleFactory();
        }
        return null;
    }
}

MobileCompany.java

public enum MobileCompany {
    APPLE, MICROSOFT, GOOGLE
}

Client.java

public class Client {
    public static void main(String[] args) {
        MobileManufactureFactory objMobileManufa = MobileFactory.getMobilesBasedOnManufacturer(MobileCompany.APPLE);
        Mobiles objMobile = objMobileManufa.getManufacturerDetails();
        objMobile.getMobileModels();
    }
}

Output

 Iphone 13,14 and 15

When Singleton should be used?
Singleton should be used incase creation of Object is costly or heavy I.E. DBConnection. It should not be used if the Object is mutable.

  1. Eager initialization
  2. Lazy initialization
  3. Static block initialization
  4. Using Synchronized method
  5. Using Synchronized block
  6. Double Checked Locking
  7. Enum Singleton
  8. Initialization on demand holder idiom

3 Things are common across all singleton implementation

private constructor
public static getInstance Method
private static instance field

Eager initialization
An 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 is similar to eager initialization, except that an instance of class is created in the static block that provides an 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 occurred in creating singleton instance");
		}
	}

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

Using Synchronized Method
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;
    }    
}

Using Synchronized Block
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. Refer the link for the same Link

ThreadSafeSing.java

package com.mugil.singleton;

public class ThreadSafeSing {
    private static ThreadSafeSinginstance;
    
    private ThreadSafeSing(){}
    
    public static ThreadSafeSing getInstance(){
        Synchronized(ThreadSafeSing.class){ 
          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. The performance hit happens when two threads try to get the instance of object in getInstance() method but only one is allowed within Synchronized block while the other needs to wait until the first is done checking irrespective of the instance is already created or not.

In the Below method of Implementing Singleton, we again use Synchronized Block but we do the check for the availability of the object instance even before taking lock.

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
enum fields are compile time constants, but they are instances of their enum type. And, they’re constructed when the enum type is referenced for the first time.
ENUMSingleton.java
Simple Singleton using enum for DBConnection

public enum EnumSingleton
{
    INSTANCE;

    // instance vars, constructor
    private final Connection connection;

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

    public Connection getConnection(){
       return connection;
    }

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

The way it works we can either use getInstance() method or directly call EnumSingleton.INSTANCE to access connection Object.

The Connection can be created using the Below Code

  Connection Conn = Singleton.getInstance().getConnection();

Minimal Implementation using ENUM

public enum MySingleton {
  INSTANCE;   
}

In the above code we may get a doubt how the object is created as we have a empty private constructor which is never invoked?.

The above code gets converted as one below. Above code has an implicit empty constructor. Lets make it explicit instead,

public enum MySingleton {
    INSTANCE;
    private MySingleton() {
        System.out.println("Here");
    }
}

Now when we make a call as below the private constructor is invoked and object gets created

public static void main(String[] args) {
    System.out.println(MySingleton.INSTANCE);
}

Output

Here
INSTANCE

Initialization on demand holder idiom
How it works?

  1. The Below implementation is a lazy loading and thread safe method of creating Singleton
  2. On calling the getInstance() method the lazySingletonClass would be initialized which in turn makes the INSTANCE to be initialized.
  3. Class initialization is inherently thread-safe and if you can have an object initialized on class initialization the object creation too are thread-safe.
  4. Singleton instance variable will never be created and or initialized until getInstance() is invoked. And again since class initialization is thread-safe the instance variable of IntiailizationOnDemandClassholder will be loaded safely, once and is visible to all threads.
public class Singleton {
    private Singleton(){}

    public static class lazySingletonClass{
      private static final Singleton INSTANCE = new Singleton();
    }

    public Singleton getInstance(){
        return lazySingletonClass.INSTANCE;
    }
}
When Object is Created Thread Safe Performance Comments
Eager Initialization Object Gets Created once the Class is Loaded Yes Bad Object is created everytime when the class is accessed
Lazy Initialization Object is Created once required No In lazy initialization you give a public API to get the instance. In multi-threaded environment it poses challenges to avoid unnecessary object creation
Static Block Initialization Object is Created once Static Block is loaded Yes Bad Not a good idea to load resources from static block as it causes performance hit during app startup
Synchronized Method Object is Created once getInstance is called Yes Bad Thread safety is guaranteed.Slow performance because of whole method locking is done
Synchronized Block Object is Created once getInstance is called No Two singleton instances may be created when context switching happens after checking instance is null
Double Checked Locking Object is Created once getInstance is called Yes Good Instance check is done twice
Enum Implementation Object Created using enum is referenced Yes Good
Initialization on demand holder idiom Object Created when static class is initiazlied by calling getInstance method Yes Good Class initialization is inherently thread-safe and if you can have an object initialized on class initialization the object creation too are thread-safe

Note
Dont be confused between Class Loading and Initialization. In the Initialization on demand holder method of singleton you can easily get confused as the static inner class wont be loaded when the outer class loads. The implementation relies on the fact that during initialization phase of execution within the Java Virtual Machine (JVM) as specified by the Java Language Specification (JLS) When the class Singleton is loaded by the JVM, the class goes through initialization. Since the class does not have any static variables to initialize, the initialization completes trivially. The static class definition lazySingletonClasswithin it is not initialized until the JVM determines that lazySingletonClassmust be executed. The static class lazySingletonClassis only executed when the static method getInstance is invoked on the class

The static class lazySingletonClass is only executed when the static method getInstance is invoked on the class Singleton , and the first time this happens the JVM will load and initialize the lazySingletonClass class. The initialization of the lazySingletonClassclass results in static variable INSTANCE being initialized by executing the (private) constructor for the outer class Something. Since the class initialization phase is guaranteed by the JLS to be sequential, i.e., non-concurrent, no further synchronization is required in the static getInstance method during loading and initialization

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();
  }
}

What is Template Pattern?
Template pattern, an abstract class exposes a ways to execute its methods. The subclasses can override the method implementation as per need but the invocation is to be in the same way as defined by an abstract class

When to use Template Pattern?

  1. When behaviour of an algorithm can vary, you let subclasses implement the behaviour through overriding
  2. You want to avoid code duplication, implementing variations of the algorithm in subclasses
  3. You want to control the point that subclassing is allowed.

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

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.