Factory mode is widely used, and can be seen everywhere in JDK source code and major mainstream frameworks. Generally, classes named after Factory, such as SqlSessionFactory in Mybatis and BeanFactory in Spring, are typical representatives of Factory mode.

1. Simple factory model

1.1 concept

Simple factory pattern, also known as static factory pattern, belongs to the creation pattern of design pattern. The simple factory pattern decouples classes by providing a static method to create instances of the class: the client does not need to know how the object was created, just calls the simple factory pattern method to create instances of the class, thus clarifying the responsibilities of each class.

1.2 the sample

Simple factory model, take the production of automobile tires as an example.

1.2.1 entity class

  • General tire properties
public class Tire {
    /** * Generic attributes */
    private String common;
}
Copy the code
  • Mercedes tire

Contains common attributes and has its own unique attributes

public class TireForBenz extends Tire{


    Tire tire;
    /** * unique attributes */
    private String benz;

    public TireForBenz(a) {
        this.benz = "Get Benz tires.";
    }


    @Override
    public String toString(a) {
        return "["+this.benz +"]"; }}Copy the code
  • BMW tires

Contains common attributes and has its own unique attributes

public class TireForBwm extends Tire{

    Tire tire;

    /** * unique attributes */
    private String bwm;

    public TireForBwm(a) {
        this.bwm = "Get Bwm tires.";
    }

    @Override
    public String toString(a) {
        return "["+this.bwm +"]"; }}Copy the code

1.2.2 Production process

  • Abstract method of producing tires, each production line has its own way of producing
public interface TireFactory {

    Tire produceTire(a);
}
Copy the code
  • Benz tire production line

Rewrite the method of producing tires to return to Benz type tires.

public class BenzTireFactory implements TireFactory {

    /** ** mercedes-benz tires */
    @Override
    public Tire produceTire(a) {
        System.out.println("Mercedes-benz tires in production...");
        return newTireForBenz(); }}Copy the code
  • BMW tire production line

Rewrite the method of producing tires to return to BMW type tires.

public class BwmTireFactory implements TireFactory {

    /** * produces BMW tires */
    @Override
    public TireForBwm produceTire(a) {
        System.out.println("BMW tire production...");
        return newTireForBwm(); }}Copy the code

1.2.3 Tire Factory

Call the corresponding production line through the incoming brand name to produce the corresponding brand tires

public class SimpleFactoryMode {

    public static TireFactory produceCar(String name) {
        if ("BenzTireFactory".equals(name)) {
            return new BenzTireFactory();
        }
        if ("BwmTireFactory".equals(name)) {
            return new BwmTireFactory();
        }
        return null; }}Copy the code

1. Test

The client gets the instance object through the factory class.

  • The test method
 @Test
public void simpleFactoryModeTest(a) {
    // Make Mercedes tires
    TireFactory benz = SimpleFactoryMode.produceCar("BenzTireFactory");
    if (null! = benz) { benz.produceTire(); }else {
        System.out.println("The factory is temporarily unable to produce Mercedes tires.");
    }
    // Make BMW tires
    TireFactory bwm = SimpleFactoryMode.produceCar("BwmTireFactory");
    if (null! = bwm) { bwm.produceTire(); }else {
        System.out.println("The factory is temporarily unable to produce BMW tires.");
    }
    // Make Honda tire (factory does not have this method)
    TireFactory honda = SimpleFactoryMode.produceCar("Honda");
    if (null! = honda) { honda.produceTire(); }else {
        System.out.println("The factory is temporarily unable to produce Honda tires."); }}Copy the code
  • The results of
Benz tire production... BMW tire production... The factory is temporarily unable to produce Honda tiresCopy the code

This method can indeed complete the production of different brands of tires, however, there is a problem: method parameters are strings, controllability needs to be improved.

1.3 Simple factory mode optimization

Instead of relying on the string passed in to determine what object needs to be created, the client simply passes in the concrete implementation class and creates the object through Java reflection.

public static TireFactory produceCar(Class<? extends TireFactory> clazz) {
    try {
        // Create objects through Java reflection
        return clazz.newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}
Copy the code

Every time an object is created, it is created by reflection, so there is a performance cost.

  • test
public void simpleFactoryModeUpgradeTest(a) {
    // Make Mercedes tires
    TireFactory benzTire = SimpleFactoryMode.produceCar(BenzTireFactory.class);
    TireForBenz benz = (TireForBenz) benzTire.produceTire();
    System.out.println(benz.toString());
    // Make BMW tires
    TireFactory bwmTire = SimpleFactoryMode.produceCar(BwmTireFactory.class);
    TireForBwm bwm = (TireForBwm) bwmTire.produceTire();
    System.out.println(bwm.toString());
}
Copy the code
  • The results of
Benz tire production... [Get Benz tire] BMW tire production... [Get Bwm tires]Copy the code

1.4 summary

The simple factory pattern does decouple code to a certain extent, and this decoupling is characterized by the fact that it separates object creation from usage. The essence of this pattern is to pass in an argument and do if… Else to return objects of different types. The disadvantages are also obvious, not matching the open/close principle (for example, adding a Porsche tire production requires modifying the factory class SimpleFactoryMode.java in addition to adding entities and production methods). Therefore, if you need to add new types, you have to modify the original code, violating the open closed principle.

  • Advantages of the simple factory model:
  1. The software architecture is simply optimized, and the responsibilities and rights of each functional module are clarified.
  2. With the factory class, the outside world does not need to directly create concrete product objects, but is responsible for consumption, and does not need to care about how objects are created internally.
  • Disadvantages of the simple factory pattern:
  1. Before the improvement of the simple factory model, all the creation logic is concentrated in a factory class. The classes that can be created can only be considered. If new classes need to be added, the factory class must be changed.
  2. With the continuous increase of specific products, the simple factory model before the improvement may have the need to create different instances according to different conditions of the common class. This kind of judgment on conditions and judgment on specific product types are intermingled, which is difficult to avoid the spread of functional modules and is detrimental to the maintenance and expansion of the system.
  3. The improved simple factory mode is mainly less efficient with reflection.

Second, factory method mode

  • What is the key to the simple factory model violating the open close principle?

It centralizes the creation of all objects in the same factory class. Therefore, when a new object is added, the shared factory class will need to be modified, violating the open and closed principle.

  • The solution

Since the point is that all object creation is coupled to this unique factory class, I configure a separate factory class for each object that creates only objects of its own type. Wouldn’t that solve the coupling problem?

2.1 concept

The factory method pattern defines an interface for creating objects, but lets the class that implements the interface decide which class to instantiate. The factory method lets class instantiation be deferred to subclasses. In the factory method pattern, users only need to care about the factory corresponding to the desired product, not the creation details, and adding new products conforms to the open and closed principle.

2.2 the sample

Factory approach model, take engine production as an example.

2.2.1 entity

  • General attributes of the engine
public class Engine {

    /** ** Model */
    private String common;

}
Copy the code
  • Benz engine

Contains common attributes and has its own unique attributes

public class EngineForBenz extends Engine{

    Engine engine;
    /** * unique attributes */
    private String benz;

    public EngineForBenz(a) {
        this.benz = "Get the Benz engine";
    }

    @Override
    public String toString(a) {
        return "["+this.benz +"]"; }}Copy the code
  • BMW engine

Contains common attributes and has its own unique attributes

public class EngineForBwm extends Engine{

    Engine engine;
    /** * unique attributes */
    private String bwm;

    public EngineForBwm(a) {
        this.bwm = "Get the Bwm engine.";
    }

    @Override
    public String toString(a) {
        return "["+this.bwm +"]"; }}Copy the code

2.2.2 Production Process (Engine factory)

  • Abstract factory class, define the method of producing engine, each production line to achieve their own
public interface EngineFactory<T> {

    Engine produceEngine(a);

}
Copy the code
  • Set up Benz sub-plant to realize its process
public class BenzEngineFactory implements EngineFactory<EngineForBenz> {

    /** ** produces Mercedes Benz engine */
    @Override
    public Engine produceEngine(a) {
        System.out.println("Mercedes-benz engine production...");
        return newEngineForBenz(); }}Copy the code
  • Create a baumaz factory to implement its process
public class BwmEngineFactory implements EngineFactory<EngineForBwm> {

    /** * produces BMW engine */
    @Override
    public Engine produceEngine(a) {
        System.out.println("BMW engine production...");
        return newEngineForBwm(); }}Copy the code

2.2.3 test

@Test
public void factoryModeTest(a) {
    // Build Mercedes engines
    EngineFactory car = new BenzEngineFactory();
    EngineForBenz benz = (EngineForBenz) car.produceEngine();
    System.out.println(benz.toString());
    // Make BMW engines
    EngineFactory carFactory = new BwmEngineFactory();
    EngineForBwm bwm = (EngineForBwm) carFactory.produceEngine();
    System.out.println(bwm.toString());
}
Copy the code
  • The results of
Benz engine production... [Get Benz engine] BMW engine production... [Get Bwm engine]Copy the code

2.3 summary

The factory method mode easily solves the problem of the simple factory mode and conforms to the open and closed principle. In the example above, when a Porsche needs to be added, it only needs to provide a corresponding engineForbsj.java to implement the produceEngine() method. No modification is required for the original code.

But each type of object has a factory class that corresponds to it. If the object type is very large, it means that many factory implementation classes need to be created, causing the number of classes to swell and causing some trouble for subsequent maintenance.

  • disadvantages
  1. The client (application layer) does not depend on the details of how product class instances are created, implemented, and so on;
  2. A class uses its subclasses to specify which object to create.
  • disadvantages
  1. The number of classes is easy to excessive, increasing the complexity;
  2. The system is abstract and difficult to understand.

Abstract factory model

Abstract factory pattern appears to solve the problems of factory method pattern, which can be regarded as the upgrade of factory method pattern.

3.1 background

  • A scenario where the number of classes expands

The objects created by the factory method pattern are ultimately the same class of objects. Take automobile production as an example. Both tires and engines are part of automobile production and belong to the process of automobile production. The diagram below:

As can be seen from the figure above, although they are divided into Mercedes and BMW, from the perspective of factory method, they both belong to the category of automobile, which leads to the need to specify a separate factory class for each part, resulting in the problem of class expansion.

  • The solution

In this case, we can designate a factory for each type of car, and then let different production lines produce the products they need, as shown in the figure below

In this way, when the number of components in each category is very large, it can be called a product family. The abstract factory pattern is designed to create a series of objects in product families, which can greatly improve the development efficiency and reduce the maintenance cost when a large number of objects need to be created.

3.2 the sample

Since the Mercedes tire/BMW tire/Mercedes engine/BMW engine entity was created earlier, it is used directly here.

3.2.1 Automobile Factory (Top-level Abstract Factory)

The class already contains tire/engine production, specific entity keys one/two related entities.

public interface CarFactory {

    /** * ready for production */
    void init(a);

    /** **@return* /
    Tire produceTire(a);

    /** * Produce engine *@return* /
    Engine produceEngine(a);
}
Copy the code

3.2.2 Mercedes-Benz Product Family (Mercedes-Benz Factory)

public class BenzCarFactory implements CarFactory{


    @Override
    public void init(a) {
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - mercedes-benz to prepare production -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
    }

    @Override
    public Tire produceTire(a) {
        System.out.println("We're making Mercedes tires.");
        return new TireForBenz();
    }

    @Override
    public Engine produceEngine(a) {
        System.out.println("Making Mercedes engines.");
        return newEngineForBenz(); }}Copy the code

3.2.2 BMW Product Family (BMW Factory)

public class BwmCarFactory implements CarFactory{


    @Override
    public void init(a) {
        System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- BMW car production -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
    }

    @Override
    public Tire produceTire(a) {
        System.out.println("Making BMW tires.");
        return new TireForBwm();
    }

    @Override
    public Engine produceEngine(a) {
        System.out.println("Making BMW engines.");
        return newEngineForBwm(); }}Copy the code

3.2.3 test

@Test
public void abstractFactoryModeTest(a) {
    // Production of parts for Mercedes-benz vehicles
    CarFactory benz = new BenzCarFactory();
    benz.init();
    TireForBenz benzTire = (TireForBenz) benz.produceTire();
    System.out.println(benzTire.toString());

    EngineForBenz benzEngine = (EngineForBenz) benz.produceEngine();
    System.out.println(benzEngine.toString());

    // Generate parts D of BMW vehicle
    CarFactory bwm = new BwmCarFactory();
    bwm.init();
    TireForBwm bwmTire = (TireForBwm) bwm.produceTire();
    System.out.println(bwmTire.toString());

    EngineForBwm bwmEngine = (EngineForBwm) bwm.produceEngine();
    System.out.println(bwmEngine.toString());
}
Copy the code
  • The results of
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- mercedes-benz to prepare production -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- is producing Mercedes tire [get Benz tire] [get] Benz engine is producing a Mercedes engine -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- BMW to prepare production -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- is producing BMW tire [get] BMW tire is producing the BMW engine [get] BMW engineCopy the code

3.3 thinking

Since the abstract factory pattern is an upgrade of the factory method pattern, what exactly is the upgrade?

In fact, the original production of a single product has been upgraded to the production of a series of products. Imagine that in the example of the car above, only one component is produced for each brand of car. For example, only the engine is produced, and no other components such as tires are produced, as shown below

Did you find anything? The abstract factory pattern has been transformed into the factory method pattern we talked about earlier! In other words, your abstract factory pattern degenerates into a factory method pattern when only one product is produced in your product family. Conversely, when producing multiple products, the factory method pattern evolves into the abstract factory pattern.

3.4 summary

The abstract factory pattern can greatly improve development efficiency when creating a large family of objects designed to produce a family of products, rather than a single product.

If you need to add a new product family, for example, adding a Porsche car, you can simply add a Porsche car factory implementation class without affecting the existing code at all.

But suppose I need to add another component, like a reversing image, to the car, what do I do? You need to add an interface to the CarFactory interface to return the reversing image object. This can not be added…… All brand car implementation classes need to modify and add the implementation of this method, which violates the open and close principle.

  • Advantages of the Abstract Factory pattern:

Creating a large number of series of objects can greatly improve development efficiency and reduce maintenance costs.

  • Disadvantages of the Abstract Factory pattern:
  1. It specifies all possible product sets to be created. It is difficult to extend new products in the product family, and the interface of the abstract factory needs to be modified.
  2. The system is abstract and difficult to understand.

Four,

4.1 How to Choose

All three forms of factory mode are introduced, so how should we choose in actual development?

  1. In terms of design principles, simple factory mode does not match the open and close principle. But surprisingly, in the real world, the simple factory model is the most used.
  2. The factory method pattern is specifically designed to solve the task of creating a single object. The pattern itself is fine and conforms to the open and closed principle. But there is the problem of factory class expansion. This is a good choice if you don’t have many factory classes to create.
  3. The abstract factory pattern was born to produce a family of products. So if you need to create a large number of objects, but there are distinct product family characteristics between the objects, this is a good time to use the abstract factory pattern.

4.2 Sample Source Code

Github sample code

4.3 Technical Communication

  1. Travelogue blog: https://www.dustyblog.cn
  2. Dust blog – Gold digging
  3. Travelogue Blog – Blog Garden
  4. Github
  5. The public,


    Refer to the article