Factory pattern


Factory Pattern is one of the most commonly used design patterns in Java. This type of design pattern is a creational pattern, which provides an optimal way to create objects.

In the factory pattern, we do not expose the creation logic to the client when creating an object, and point to the newly created object by using a common interface.

Introduction

Intent: Define an interface for creating objects and let its subclasses decide which factory class to instantiate. The factory pattern delays the creation process until the subclasses Class proceeds.

Mainly solve: Mainly solve the problem of interface selection.

When to use: When we explicitly plan to create different instances under different conditions.

How to solve: Let its subclass implement the factory interface and return an abstract product.

Key code: The creation process is executed in its subclass.

Application examples: 1. If you need a car, you can pick it up directly from the factory without worrying about how the car is made and the specific implementation inside it. . 2. To change the Hibernate database, you only need to change the dialect and driver.

Advantages: 1. If a caller wants to create an object, he only needs to know its name. 2. High scalability. If you want to add a product, you only need to extend a factory class. 3. Shield the specific implementation of the product, and the caller only cares about the product interface.

Disadvantages: Every time you add a product, you need to add a specific class and object implementation factory, which doubles the number of classes in the system and increases the system complexity to a certain extent. The complexity also increases the dependence on the specific classes of the system. This is not a good thing.

Usage scenarios: 1. Logger: Records may be recorded to local hard disk, system events, remote servers, etc. Users can choose where to record logs. 2. Database access, when the user does not know which type of database will be used by the final system, and when the database may change. 3. Designing a framework for connecting to the server requires three protocols, "POP3", "IMAP", and "HTTP". These three can be used as product categories to jointly implement an interface.

Note: As a class creation pattern, the factory method pattern can be used wherever complex objects need to be generated. One thing to note is that complex objects are suitable for using the factory pattern, while simple objects, especially those that can be created only through new, do not need to use the factory pattern. If you use the factory pattern, you need to introduce a factory class, which will increase the complexity of the system.

Implementation

We will create a Shape interface and an entity class that implements the Shape interface. The next step is to define the factory class ShapeFactory.

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

工厂模式的 UML 图

Step 1

Create an interface.

Shape.java

public interface Shape {
   void draw();
}

Step 2

Create an entity class that implements 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 entity classes based on the given information.

ShapeFactory.java

public class ShapeFactory {
	
   //使用 getShape 方法获取形状类型的对象
   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 this factory to obtain the object of the entity class by passing type information.

FactoryPatternDemo.java

public class FactoryPatternDemo {

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

      //获取 Circle 的对象,并调用它的 draw 方法
      Shape shape1 = shapeFactory.getShape("CIRCLE");

      //调用 Circle 的 draw 方法
      shape1.draw();

      //获取 Rectangle 的对象,并调用它的 draw 方法
      Shape shape2 = shapeFactory.getShape("RECTANGLE");

      //调用 Rectangle 的 draw 方法
      shape2.draw();

      //获取 Square 的对象,并调用它的 draw 方法
      Shape shape3 = shapeFactory.getShape("SQUARE");

      //调用 Square 的 draw 方法
      shape3.draw();
   }
}

Step 5

Verify the output.

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