Factory mode of design mode

Posted by artcalv on Mon, 24 Jan 2022 17:40:41 +0100

Factory mode:

When the creation logic is complex, you can consider using factory mode to encapsulate the creation process of objects and separate the creation and use of objects.

Factory mode, belonging to creation type

I put the actual code in Github: https://github.com/liangtengyu/DesignPatterns-for-Java

Application scenario:

Before learning a design pattern, we first understand its usage scenario, which can help us understand it faster. Compared with directly creating objects with new, what are the benefits of creating objects with factory pattern?

There are two main situations:

  • The first case is an example similar to rule configuration parsing. There is an if else branch judgment in the code, which dynamically creates different objects according to different types. In view of this situation, we can consider using the factory pattern to extract this large block of if else object creation code and put it into the factory class.

  • In another case, although we do not need to create different objects according to different types, the creation process of a single object itself is complex, and we can also consider using the factory pattern.

Benefits: because the factory pattern relies on abstract architecture, it assigns the task of instantiating products to the implementation class, which has good scalability. In other words, when the system needs better scalability, the factory mode can be considered, and different products can be assembled in different implementation factories. Generally speaking, it is to reduce the impact of code changes on product functions

Implementation method:

Simple Factory

First, let's look at what a simple factory model is. Let's explain it with an example.

Simple factory mode

public class Cocacola implements Cola {
    public String getCola() {
        return "Coca Cola";
    }
}
public class ColaFactory {

    public static Cola getInstance(Integer  colaType) {
        if (1 == colaType) {
            return new Cocacola();
        } else if (2 == colaType) {
            return new Pepsicola();
        } else {
            return new Fakecola();
        }
    }

}
 public static void main(String[] args) {
        String drink = ColaFactory.getInstance(1).drink();
        System.out.println(drink);
    }
    //Coca Cola

Although there are many if branch judgment logic in the code implementation of simple factory mode, which violates the opening and closing principle, such code implementation has no problem in most cases by balancing scalability and readability.

Factory Method

The factory method is a further extension of the simple factory. This is because the simple factory violates the opening and closing principle. At this time, the factory method can perfectly solve this problem! Next, let's see how it is solved!

Plant method - Project

For the application scenario of rule configuration file parsing, the Factory mode needs to create many additional Factory classes, which will also increase the complexity of the code. Moreover, each Factory class only performs a simple new operation, the function is very thin (only one line of code), and there is no need to design an independent class. Therefore, in this application scenario, the simple Factory mode is easy to use, More suitable than Factory method mode

public interface ColaFactory {//Factory interface
    Cola getCola();
}
public class CocaColaFactoryImpl implements ColaFactory {//Realize Coca Cola factory
    public Cola getCola() {
        return  new Cocacola();
    }
}
public static void main(String[] args) {
    //When the factory method requires a coke, it is taken directly from the corresponding factory, but not from a factory according to judgment like a simple factory
    //Each kind of coke corresponds to a factory
    ColaFactory pepsiColaFactory = new PepsiColaFactoryImpl();
    Cola cola = pepsiColaFactory.getCola();
    cola.getCola();
}

When should I use the factory method pattern instead of the simple factory pattern?

The reason why a code block is separated and independent as a function or class is that the logic of the code block is too complex. After stripping, the code can be clearer, more readable and maintainable.

However, if the code block itself is not complex, just a few lines of code, there is no need to split it into separate functions or classes. Based on this design idea, when the object creation logic is complex, not just a simple new, but to combine other class objects and do various initialization operations, we recommend using the factory method mode to split the complex creation logic into multiple factory classes, so that each factory class will not be too complex. Using the simple factory pattern and putting all the creation logic into a factory class will make the factory class very complex.

In addition, in some scenarios, if objects are not reusable, the factory class will return different objects every time. If we use the simple factory pattern to implement, we can only choose the first implementation that contains if branch logic. If we also want to avoid annoying if else branching logic, we recommend using the factory method pattern at this time.

Abstract Factory

The application scenario of the abstract factory pattern is quite special. It is not commonly used in the first two. Let's have a brief look

The simple factory only abstracts the coke products, the factory method abstracts the coke factory, and the abstract factory abstracts the factory method again

Light from the concept may not be easy to understand, let's take an example

Demand: now the product line has been adjusted. Although our coke has its own brand, they are transparent bottles. We need to make our own characteristics Different brands of cola need to be painted with different colors

Thinking: if we couple the production of coke and color spraying into the code of the factory method at this time, the subsequent adjustment will be very troublesome, and it also violates the opening and closing principle. It is open to expansion and closed to modification, then it is more appropriate for us to use the abstract factory at this time

public abstract class ColaAbstractFactory {//Create abstract factory class
    abstract ColaFactory getCola(String cola);
    abstract ColorFactory getColor(String color);
}
public class ColaAbstractFactoryImpl extends ColaAbstractFactory {

        //Implement abstract classes
   public ColaFactory getCola(String cola) {
        if ("cocacola".equals(cola)) {
            return new CocaColaFactoryImpl();
        } else if ("fake".equals(cola)) {
            return new FakeColaFactoryImpl();
        } else if ("pepsi".equals(cola)) {
            return new PepsiColaFactoryImpl();
        } else
            return null;
    }

    public ColorFactory getColor(String color) {
        if ("yellow".equals(color)) {
            return new YellowColorFactoryImpl();
        } else if ("blue".equals(color)) {
            return new BlueColorFactoryImpl();
        } else if ("red".equals(color)) {
            return new RedColorFactoryImpl();
        } else
            return null;
    }
}
public class RedColorFactoryImpl implements ColorFactory {//Spray for different colors If other colors are similar, don't paste them again
    public String getColor() {
        System.out.println("Spray red bottle body");
        return "Red bottle";
    }
}

Finally, we want to get coke + red bottle

public static String getColaAndColor(String cola,String color){
    ColaAbstractFactoryImpl colaAbstractFactory = new ColaAbstractFactoryImpl();

    ColaFactory cola = colaAbstractFactory.getCola(cola);
    ColorFactory red = colaAbstractFactory.getColor(color);

    Cola col = cola.getCola();
    String colo = red.getColor();
    return col.getCola()+"-"+colo;
}
public static void main(String[] args) {
    String colaAndColor = FactoryProducer.getColaAndColor("cocacola", "red");
    System.out.println(colaAndColor);

}
//output:
Spray red
 Production of Coca Cola
 Coca Cola-Red bottle

Pay attention to the official account: java treasure