This is the first day of my participation in the August Text Challenge.More challenges in August

Challenge yourself in August, thanks to the Nuggets!

There are three types of factory patterns, namely simple factory, factory method and abstract factory, which are described below.

Simple factory

The simple Factory pattern is not really a design pattern, but a coding habit. Let’s start with a UML diagram of the simple factory pattern:

Here is an example of what the simple factory pattern is.

Now there is an interface for food, and concrete implementations of food are noodles and hamburgers. There is a food factory, which is used to produce food, producing different food according to different parameters that are passed in.

Food Interface:

/ * * *@Author: JonesYong
 * @Data: 2021-08-01
 * @Description: * /
public interface Food {
    void createFood(a);
}
Copy the code

Noodles and burgers:

/ * * *@Author: JonesYong
 * @Data: 2021-08-01
 * @Description: * /
public class Noodle implements Food {

    @Override
    public void createFood(a) {
        System.out.println("noodle was created."); }}Copy the code
/ * * *@Author: JonesYong
 * @Data: 2021-08-01
 * @Description: * /
public class Hamburger implements Food {


    @Override
    public void createFood(a) {
        System.out.println("Hamburger was created."); }}Copy the code

Here’s a look at food factories:

/ * * *@Author: JonesYong
 * @Data: 2021-08-01
 * @Description: * /
public class SimpleFactory {
    public static Food getFoodInstance(String type) {
        Food food = null;
        switch (type) {
            case "Noodle":
                food = new Noodle();
                break;
            case "Hamburger":
                food = new Hamburger();
                break;
        }
        returnfood; }}Copy the code

Like this, different objects are produced based on different parameters passed in, avoiding the creation of useless objects, which we call the simple factory pattern. However, the simple factory has obvious disadvantages. For example, when there is another kind of food, we have to modify the code of the food factory, which violates the open and closed principle.

The factory method

As mentioned above, the simple factory pattern, while simple to use, violates the open and closed principle. This works well if the factory method is used. Here is the UML for the factory method:

The simple factory mode violates the open and close principle. Every time we add a food, we need to go to the food factory to modify the corresponding code!

So how does the factory approach prevent this from happening? A closer look at the UML diagram shows that each food corresponds to a food factory. If we want to add a new food, we need to create a factory to produce the corresponding food. The code details are as follows:

Here is a food interface abstraction:

/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public interface FoodFactory {
    Food createFood(a);
}
Copy the code

There are two implementation classes:

/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public class NoodleFactory implements FoodFactory {
    @Override
    public Food createFood(a) {
        return newNoodle(); }}Copy the code
/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public class HamburgerFactory implements FoodFactory{
    @Override
    public Food createFood(a) {
        return newHamburger(); }}Copy the code

In this way, when we need to add a function, we just need to re-specify a specific thing, and then we add the corresponding factory on the client. This does not violate the open close principle, and resolves the client and service coupling!

Writing, writing, as if I knew something was wrong with you. Think about it, if we added one food item at a time, we would need to add another factory. If there is more and more food, won’t there be more and more extra factory classes, and then there will be a class explosion?

This is where the abstract factory comes in, which neatly solves the explosion like situation.

The abstract factory

Let’s take a look at abstract factory UML:

In fact, abstract factories are not easy to understand. Here is an example.

The business now needs to produce drinks as well as food. Added a beverage interface as follows:

/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public interface Drink {
    void createDrink(a);
}
Copy the code

Its two implementation classes are as follows:

/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public class Milk implements Drink {
    @Override
    public void createDrink(a) {
        System.out.println("Milk was created."); }}Copy the code
/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public class Cola implements Drink {
    @Override
    public void createDrink(a) {
        System.out.println("Cola was created."); }}Copy the code

In context, we are a FoodFactory, and food factories already contain food and drink, and we cannot recreate DrinkFactory outside of the FoodFactory (the company refuses to split). So what happens now? Nor would it be appropriate to create a DrinkFactory inside a FoodFactory that is different from NoodleFactory and HamburgerleFactory.

What can be done? I was thinking, is it possible to sell these drinks together with specific food? In fact, this is somewhat similar to the business structure of the company. Each sub-business is assigned to an independent large department to complete, which can be divided into front-end, back-end and algorithm. Numerous sub-businesses form the business line of the whole company.

The analogy is as follows: the business of the whole company is equivalent to FoodFactory, under which there are many large departments (sub-businesses) such as KFCFactory and ChinaFactory, etc., which can be divided into front-end and back-end (producing different food and beverage).

The code details are as follows:

Factory interface, every food factory needs to implement this interface:

/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public interface FoodFactory {
    Food createFood(a);

    Drink createDrink(a);
}
Copy the code

Food Factory has two implementation classes, one for creating different foods:

/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public class ChinaFactory implements FoodFactory {

    @Override
    public Food createFood(a) {
        return new Noodle();
    }

    @Override
    public Drink createDrink(a) {
        return newMilk(); }}Copy the code
/ * * *@Author: JonesYong
 * @Data: 2021-08-02
 * @Description: * /
public class KFCFactory implements FoodFactory {

    @Override
    public Food createFood(a) {
        return new Hamburger();
    }

    @Override
    public Drink createDrink(a) {
        return newCola(); }}Copy the code

Abstract factories seem to solve the problem of quasi-explosions, but if you think about it, there are still problems. If at this time, our demand increases and we also need to produce ice cream, it is bound to modify the corresponding function of the original Factory, which violates the open and closed principle.

Well, that concludes our introduction to the factory pattern.

Additional, because the level is limited, have wrong place unavoidable, rather misdirect others, welcome big guy to point out! Code word is not easy, thank you for your attention! 🙏