Easy Tutorial
❮ Design Pattern Intro Transfer Object Pattern ❯

Factory Pattern

The Factory Pattern (Factory Pattern) is one of the most commonly used design patterns in Java. This type of design pattern falls under the creational pattern category, providing an optimal way to create objects.

In the Factory Pattern, we do not expose the creation logic to the client when creating objects, and we use a common interface to point to newly created objects.

Introduction

Intent: Define an interface for creating an object, allowing its subclasses to decide which class to instantiate. The Factory Pattern delays the instantiation process to its subclasses.

Main Solution: Mainly solves the problem of interface selection.

When to Use: We explicitly plan to create different instances under different conditions.

How to Solve: Allow subclasses to implement the factory interface, returning an abstract product.

Key Code: The creation process is executed in its subclasses.

Application Examples:

  1. You need a car and can directly pick it up from the factory without worrying about how it is made or its specific implementation.
  2. Hibernate can switch databases by changing the dialect and driver.

Advantages:

  1. A caller wants to create an object, knowing its name is sufficient.
  2. High scalability, adding a product only requires extending a factory class.
  3. Hides the specific implementation of the product, the caller only cares about the product's interface.

Disadvantages: Every time a product is added, a concrete class and object implementing the factory are needed, which doubles the number of classes in the system, increasing the system's complexity and dependency on specific classes. This is not a good thing.

Usage Scenarios:

  1. Logger: Logging may be recorded to local hard drives, system events, remote servers, etc., allowing users to choose where to log.
  2. Database access, when users do not know which type of database the system will eventually use, and the database may change.
  3. Designing a server connection framework, requiring three protocols, "POP3", "IMAP", "HTTP", which can be treated as product classes implementing a common interface.

Notes: As a creational pattern, the Factory Method Pattern can be used anywhere complex objects need to be generated. It is important to note that complex objects are suitable for the Factory Pattern, while simple objects, especially those that can be created with a simple 'new', do not need the Factory Pattern. Using the Factory Pattern would introduce a factory class, increasing system complexity.

Implementation

We will create a Shape interface and concrete classes implementing the Shape interface. Next, we define a factory class ShapeFactory.

The FactoryPatternDemo class uses ShapeFactory to get Shape objects. It will pass information (CIRCLE / RECTANGLE / SQUARE) to ShapeFactory to obtain the type of object it needs.

Step 1

Create an interface:

Shape.java

public interface Shape {
   void draw();
}

Step 2

Create concrete classes implementing 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 generate objects of concrete classes based on given information.

ShapeFactory.java

public class ShapeFactory {

   // Use getShape method to get shape type objects
   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

Use the factory by passing type information to get objects of concrete classes.

FactoryPatternDemo.java

public class FactoryPatternDemo {

   public static void main(String[] args) {
      ShapeFactory shapeFactory = new ShapeFactory();

      // Get an object of Circle and call its draw method
      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

Execute the program, output result:

Inside Circle::draw() method.
Inside Rectangle::draw() method.
Inside Square::draw() method.

Other Related Articles

❮ Design Pattern Intro Transfer Object Pattern ❯