Comprehensive and thorough analysis of factory method mode

Posted by NCllns on Thu, 11 Nov 2021 07:34:37 +0100

This article is excerpted from "design patterns should be learned this way"

1. Application scenario of factory method mode

The factory method mode is mainly applicable to the following application scenarios.

(1) Creating objects requires a lot of repetitive code.

(2) The client (application layer) does not depend on the details of how product class instances are created and implemented.

(3) A class specifies which object to create through its subclasses.

UML class diagram of 2 Factory Method Pattern

The UML class diagram of the factory method pattern is shown in the figure below.

As can be seen from the above figure, the abstract factory pattern mainly includes four roles.

(1) Abstract Factory: it is the core of the Factory method pattern and is independent of the application. The Factory class of any object created in the schema must implement this interface.

(2) Concrete Factory: it is a Concrete Factory class that implements the abstract factory interface, contains logic closely related to the application, and is called by the application to create a product object.

(3) Abstract Product: it is the supertype of the object created by the factory method pattern, that is, the common parent class or jointly owned interface of the Product object.

(4) Concrete Product: this role implements the interface defined by the abstract product role. A specific product has a specific factory, and they often correspond to each other one by one.

3 general writing method of factory method mode

The following is a general description of the factory method pattern.

public class Client {
    public static void main(String[] args) {
        IFactory factory = new FactoryA();
        factory.makeProduct().doSomething();

        factory = new FactoryB();
        factory.makeProduct().doSomething();

        factory = new FactoryC();
        factory.makeProduct().doSomething();
    }

    //Abstract factory
    public interface IFactory {
        IProduct makeProduct();
    }
    //Specific factory class producing ProductA
    static class FactoryA implements IFactory {
        public IProduct makeProduct() {
            return new ProductA();
        }
    }
    //Specific factory class producing ProductB
    static class FactoryB implements IFactory {
        public IProduct makeProduct() {
            return new ProductB();
        }
    }

    //Specific factory class that produces ProductC
    static class FactoryC implements IFactory {
        public IProduct makeProduct() {
            return new ProductC();
        }
    }


    //Abstract product
    public interface IProduct {
        void doSomething();
    }

    //Specific product: ProductA
    static class ProductA implements IProduct {
        public void doSomething() {
            System.out.println("I am Product A");
        }
    }

    //Specific product: ProductB
    static class ProductB extends FactoryB implements IProduct {
        public void doSomething() {
            System.out.println("I am Product B");
        }
    }

    //Specific product: ProductC
    static class ProductC implements IProduct {
        public void doSomething() {
            System.out.println("I am Product C");
        }
    }
}

4 use factory method mode to realize product expansion

The factory method mode mainly solves the problem of product expansion. In a simple factory, with the enrichment of the product chain, if the creation logic of each course is different, the responsibilities of the factory will become more and more, which is a bit like a universal factory and is not easy to maintain. According to the principle of single responsibility, we will continue to split our functions and assign special personnel to do special work. Java courses are created by Java factories, python courses are created by Python factories, and the factories themselves are also abstracted. First, create the ICourseFactory interface.

public interface ICourseFactory {
    ICourse create();
}

Then create sub factories respectively. The code of JavaCourseFactory class is as follows.

import com.tom.pattern.factory.ICourse;
import com.tom.pattern.factory.JavaCourse;

public class JavaCourseFactory implements ICourseFactory {
    public ICourse create() {
        return new JavaCourse();
    }
}

The code of the python coursefactory class is as follows.

import com.tom.pattern.factory.ICourse;
import com.tom.pattern.factory.PythonCourse;

public class PythonCourseFactory implements ICourseFactory {
    public ICourse create() {
        return new PythonCourse();
    }
}

The client test code is as follows.

public static void main(String[] args) {
    ICourseFactory factory = new PythonCourseFactory();
    ICourse course = factory.create();
    course.record();

    factory = new JavaCourseFactory();
    course = factory.create();
    course.record();
}

Finally, look at the class diagram shown in the figure below.

Application of 5 factory method pattern in Logback source code

Look at the application of factory method pattern in Logback. Its class diagram is shown in the following figure.

As can be seen from the above figure, different factories have been separated to create different log frameworks, such as Substitute log framework, NOP log framework and Log4J log framework, so does the corresponding Logger product system, as shown in the following figure.

Topics: Java Design Pattern architecture