Factory Method Design Pattern

1.1 What is Factory Method Pattern?
  • Factory Method Design Pattern is a Creational Design Pattern that uses a factory method to deal with problem of creating objects
  • It is one of the most commonly used Design Patterns in Java.
  • This pattern is also called Virtual Constructor
1.2  Problem (Before Factory Method Pattern)

Imagine that you’re creating a electricity bill generating application. The first version of your app can only handle only Domestic and Commercial Plan. In the next version, the Institutional users want a different Plan. How will you incorporate the change ?

factory-method
Before Factory Method Pattern
package com.coding.bee.dp.creational.factory.before;
public abstract class Plan {
	public abstract  double getRate();	
	public abstract  double getFixedCost();
}
package com.coding.bee.dp.creational.factory.before;
public class CommercialPlan extends Plan {
	@Override
	public double getRate() {
		return 5.5;
	}
	@Override
	public double getFixedCost() {
		return 10;
	}
}
package com.coding.bee.dp.creational.factory.before;
public class DomesticPlan extends Plan {
	@Override
	public double getRate() {
		return 3.5;
	}
	@Override
	public double getFixedCost() {
		return 5;
	}
}
package com.coding.bee.dp.creational.factory.before;
public class ComputeBill {
	public static double getTotalElectricityCharge(Plan plan, int units) {
		return plan.getFixedCost() + plan.getRate() * units;
	}
}
package com.coding.bee.dp.creational.factory.before;
import java.util.Scanner;
public class GenerateBillClient {
	public static void main(String args[]) {
	   try (Scanner scan = new Scanner(System.in)) {
		System.out.print("Enter the name of plan: ");
		String planName = scan.nextLine();
		System.out.print("Enter number of units: ");
		int units = scan.nextInt();
		//SuperClass obj = new Subclass();
		Plan plan = null;
		if (planName.equals("DOMESTIC")) {
			plan = new DomesticPlan();
		} else if (planName.equals("COMMERCIAL")) {
			plan = new CommercialPlan();
		}
		double cost = ComputeBill.getTotalElectricityCharge(plan, units);
		System.out.print("Bill amount for " + planName + " of " + units + " units is : " + cost);
		}
	}
}

Here each time the client code needs to add new if-else condition and needs to compile again every time we introduce a new subclass. This means that the Product and Client are tightly coupled

1.3  Solution (After Factory Method Pattern)

The solution is to create a static (or Factory) method. Here the Product and Client are loosely-coupled

factory-method
After Factory Method Design Pattern
package com.coding.bee.dp.creational.factory;
public abstract class Plan {
    public abstract  double getRate();
    public abstract  double getFixedCost();
}
package com.coding.bee.dp.creational.factory;
public class CommercialPlan extends Plan {
    @Override
    public double getRate() {
      return 5.5;
   }
    @Override
    public double getFixedCost() {
      return 10;
    }
}
package com.coding.bee.dp.creational.factory;
public class DomesticPlan extends Plan {
   @Override
   public double getRate() {
     return 3.5;
   }
   @Override
   public double getFixedCost() {
     return 5;
   }
}
package com.coding.bee.dp.creational.factory;
public class InstitutionalPlan extends Plan {
  @Override
  public double getRate() {
    return 7.5;
  }
  @Override
  public double getFixedCost() {
    return 20;
  }
}
package com.coding.bee.dp.creational.factory;
public class ComputeBill {
public static double getTotalElectricityCharge(Plan plan, int units) {
    return plan.getFixedCost() + plan.getRate() * units;
 }
}
package com.coding.bee.dp.creational.factory;
public class PlanFactory {
public static Plan getPlan(String planName) {
    Plan plan = null;
    if (planName.equals("DOMESTIC")) {
        plan = new DomesticPlan();
    } else if (planName.equals("COMMERCIAL")) {
        plan = new CommercialPlan();
    }else if (planName.equals("INSTITUTION")) {
        plan = new InstitutionalPlan();
    }
    return plan;
}
}
package com.coding.bee.dp.creational.factory;
import java.util.Scanner;
public class GenerateBillClient {
public static void main(String args[]) {
    try (Scanner scan = new Scanner(System.in)) {
        System.out.print("Enter the name of plan: ");
        String planName = scan.nextLine();
        System.out.print("Enter number of units: ");
        int units = scan.nextInt();
        Plan plan = PlanFactory.getPlan(planName);
        double cost = ComputeBill.getTotalElectricityCharge(plan, units);
        System.out.print("Bill amount for " + planName + " of " + units + " units is : " + cost);
    }
}
}
1.2 When is Factory Method Used?
  • The Class/Interface needs to be extended/implemented into Subclasses
  • The Class doesn’t know which Subclasses it has to create
  • The product implementation tend to change over time, but Client remains unchanged
Watch Factory Method Design Pattern on Youtube

Leave a comment