Java Advanced Topics and Techniques

Java Design Pattern: Factory Method

Java Design Pattern: Factory Method

Introduction

The construction of an object is discussed in this creational design pattern. According to the factory design pattern, establish an interface for producing objects (such as a Java interface or an abstract class) and allow the subclasses to choose which class to instantiate. A class may defer the instantiation to one or more concrete subclasses using the factory method in the interface. These design patterns fall under the topic of creational design patterns since they discuss the instantiation of an object. If we pay attention to the name of the method, the Factory method, we may deduce that it is a factory. In general, factories are involved in creational processes, and in this case, an object is being formed.

One of the finest methods for keeping object creation logic concealed from the client is this one.

Advantages

  • The factory method pattern gives subclasses the option of selecting the kind of objects to produce.
  • By removing the requirement to tie application-specific classes into the code, it encourages loose coupling. This implies that the code only interacts with the resulting interface or abstract class, allowing it to function with any classes that extend or implement that interface.

Usage

  • when a class is unsure of the subclasses it will need to develop.
  • When a class requests that the objects to be produced be specified by its subclasses.
  • When the parent classes decide to create objects for their child classes.

Let's now examine the implementation.

Implementation

A Shape interface will be developed, along with actual classes that implement it. In the next stage, a factory class called ShapeFactory is defined.

ShapeFactory will be used by FactoryPatternDemo, our demo class, to obtain a Shape object. In order to obtain the right kind of object, it will pass ShapeFactory information (CIRCLE, RECTANGLE, or SQUARE).

Step 1: Build an interface.

Shapes.java

public interface Shape {

   void draw();

}

Step 2: Construct concrete classes that implement the interface.

Rectangle.java

public class Rectangle implements Shape {

   @Override

   public void draw() {

      System.out.println("Inside Rectangle::draw() method.");

   }

}

Square.java

public class Square implements Shape {

   @Override

   public void draw() {

      System.out.println("Inside Square::draw() method.");

   }

}

Circle.java

public class Circle implements Shape {

   @Override

   public void draw() {

      System.out.println("Inside Circle::draw() method.");

   }

}

Step 3: Create a factory to produce concrete class objects using the supplied data.

ShapesFactory.java

public class ShapeFactory {

   //To acquire an object of type shape, use the getShape method.

   public Shape getShape(String shapeType){

      if(shapeType == null){

         return null;

      }

      if(shapeType.equalsIgnoreCase("CIRCLE")){

         return new Circle();

      } else if(shapeType.equalsIgnoreCase("RECTANGLE")){

         return new Rectangle();

         

      } else if(shapeType.equalsIgnoreCase("SQUARE")){

         return new Square();

      }

      return null;

   }

}

Step 4: Utilize the factory to obtain concrete class objects by passing information like type.

FactoryPatternDemo.java

public class FactoryPatternDemo {


   public static void main(String[] args) {

      ShapeFactory shapeFactory = new ShapeFactory();


      //Obtain a Circle object and use its draw function.

      Shape shape1 = shapeFactory.getShape("CIRCLE");


      //call draw method of Circle

      shape1.draw();


      //get an object of Rectangle and call its draw method.

      Shape shape2 = shapeFactory.getShape("RECTANGLE");


      //call draw method of Rectangle

      shape2.draw();


      //get an object of Square and call its draw method.

      Shape shape3 = shapeFactory.getShape("SQUARE");


      //call draw method of square

      shape3.draw();

   }

}

Step 5: Check up the output.

Inside Circle::draw() method.

Inside Rectangle::draw() method.

Inside Square::draw() method.

Actual instances:

In JDK, this design pattern has been widely employed, including

  1. Factory method design pattern is used in the getInstance() method of the Java.util.Calendar, NumberFormat, and ResourceBundle classes.
  2. Java employs this approach to assess the values using the function valueOf() method in all wrapper classes, including Integer, Boolean, and others.
  3. Some of their examples where the factory method design pattern has been employed include java.nio.charset.Charset.forName(), java.sql.DriverManager#getConnection(), java.net.URL.openConnection(), java.lang.Class.newInstance(), and java.lang.Class.forName().
write your code here: Coding Playground

Conclusion

We've learned so far what the Factory Method Design Pattern is and how to use it. I think we now have a good idea of the benefit of this design mechanism.