Factory method model

Posted by hanhao on Wed, 26 Jan 2022 15:40:36 +0100

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

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

introduce

Intention: define an interface for creating objects, and let its subclasses decide which factory class to instantiate. The factory mode delays the creation process to the subclasses.

Main solution: mainly solve the problem of interface selection.

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

How to solve it: let its subclasses 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 up the goods directly from the factory, regardless of how the car is made and the specific implementation in the car. 2. Hibernate database only needs to change dialect and driver.

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

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

Usage scenario: 1. Log recorder: 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 what kind of database the system will use and the database may change. 3. Designing a framework for connecting to a server requires three protocols, "POP3", "IMAP" and "HTTP", which can be used as product classes to jointly implement an interface.

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

realization

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.

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

Step 1

Create an interface:

Shape.java

interface Shape {
    void draw();
}

Step 2

Create an entity class that implements the interface.

Rectangle.java

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }
}

Square.java

class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Square::draw() method.");
    }
}

Circle.java

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

class ShapeFactory {
    //Use the getShape method to get an object of shape type
    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

Using this factory, the object of the entity class is obtained by passing type information.

FactoryPatternDemo.java

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

        //Get the object of Circle and call its draw method
        Shape shape1 = shapeFactory.getShape("CIRCLE");
        //Call Circle's draw method
        shape1.draw();

        //Get the object of Rectangle and call its draw method
        Shape shape2 = shapeFactory.getShape("RECTANGLE");
        //Call the draw method of Rectangle
        shape2.draw();

        //Get the object of Square and call its draw method
        Shape shape3 = shapeFactory.getShape("SQUARE");
        //Call Square's draw method
        shape3.draw();
    }
}

Step 5

Execute the program and output the results:

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

Complete runnable Code:

package com.wenxiaowu.dp;

/**
 * Factory method model
 */
public class FactoryPatternTest {
    public static void main(String[] args) {
        ShapeFactory shapeFactory = new ShapeFactory();

        //Get the object of Circle and call its draw method
        Shape shape1 = shapeFactory.getShape("CIRCLE");
        //Call Circle's draw method
        shape1.draw();

        //Get the object of Rectangle and call its draw method
        Shape shape2 = shapeFactory.getShape("RECTANGLE");
        //Call the draw method of Rectangle
        shape2.draw();

        //Get the object of Square and call its draw method
        Shape shape3 = shapeFactory.getShape("SQUARE");
        //Call Square's draw method
        shape3.draw();
    }
}

interface Shape {
    void draw();
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Rectangle::draw() method.");
    }
}

class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Square::draw() method.");
    }
}

class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Inside Circle::draw() method.");
    }
}

class ShapeFactory {
    //Use the getShape method to get an object of shape type
    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;
    }
}

Reprint: Factory mode | rookie tutorial (runoob.com)

Topics: Java Back-end