Factory mode – get rid of the trouble that you are still single with new objects day after day!

Time:2022-1-9

preface

When we talk about Java, we can’t help thinking of a sad fact: whether you are new objects every day, but still stick to the single post. (the so-called “shortcomings” HHH of object-oriented programming). In this article, let’s learn about the factory pattern and get rid of the troubles of new objects!

Knowledge points

Traditional factory

  • Abstract classes and subclasses
  • Production and use are put together without separation, pass the name when using, and then produce the corresponding product
public class OrderPizza {

	//Constructor
	public OrderPizza() {
		Pizza pizza = null;
		String orderType; //  Type of pizza ordered
		
			orderType = getType();
			if (orderType.equals("greek")) {
				pizza = new GreekPizza();
				pizza. Setname ("Greek pizza");
			} else if (orderType.equals("cheese")) {
				pizza = new CheesePizza();
				pizza. Setname ("cheese pizza");
			} else if (orderType.equals("pepper")) {
				pizza = new PepperPizza();
				pizza. Setname ("Pepper pizza");
			} else {
				break;
			}
			//Output pizza production process
			pizza.prepare();
			pizza.bake();
			pizza.cut();
			pizza.box();
			
	}

Analysis of improvement ideas

  • It is acceptable to modify the code, but if we also have the code to create pizza in other places, it means that we also need to modify the code, and the code to create pizza often has many places.
  • Idea:Encapsulate the creation of pizza objects into a factory classIn this way, when we have a new pizza category, we only need to modify theFactory classWell, other codes that create pizza objects do not need to be modified. – > Simple factory mode

Simple factory mode (pass the product name and then if else)

A super factory, responsible for producing all kinds of products

  • On the basis of traditional factories, throughThe process of creating a productPackage into oneFactory class, realize the separation of production and use

Interface class / abstract class

package com. melo. design. Factory mode Simple factory mode;

public interface Shape {

    void draw();
}

Sub products

package com. melo. design. Factory mode Simple factory mode;

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

Factory class

package com. melo. design. Factory mode Simple factory mode;

public class ShapeFactory {

    public static Shape getShape(String shape){
        if("Circle".equals(shape)){
            return new Circle();
        }else if("Triangle".equals(shape)){
            return new Triangle();
        }
        return null;
    }
}

Caller

package com. melo. design. Factory mode Simple factory mode;

public class Main {

    public static void main(String[] args) {
        Shape circle = ShapeFactory.getShape("Circle");
        circle.draw();
    }
}

shortcoming

In short, the simple factory pattern is to let a factory class assume the responsibility of building all objects. What products the caller needs can be produced by the factory. Its disadvantages are also obvious:

  • First, if there are too many products to be produced, this model will lead to too large factory classes, assume too many responsibilities and become super classes. When the apple production process needs to be modified, modify the factory. When the pear production process needs to be modified, the factory should also be modified. That is, there is more than one reason for the modification of this class. ViolatedSingle responsibility principle
  • Second, when a new product is to be produced, a new branch must be added to the factory class. The open close principle tells us that classes should be closed to modifications. We hope that when adding new functions, we only need to add new classes instead of modifying existing classes, so this is necessaryIt violates the opening and closing principle

Factory method model

  • In the factory method pattern, weA unified factory class is no longer providedTo create all objects, but forDifferent objectsprovideDifferent factories。 That is, each object has a factory corresponding to it.
  • The factory method delays the instantiation of the class to the subclass!!!

Originally, a simple factory was a factory responsible for producing all products. Now, each object corresponds to a factory, and a factory is only responsible for producing one product

advantage

  • In this way, we have solved the single responsibility problem mentioned above, and each factory is only responsible for producing one product
  • It also solves the opening and closing principle. Each time we need to add a product, we only need to add a factory class instead of modifying the original factory class

shortcoming

  • Each time you add a product, you need to add a specific class and object implementation factory, so that the number of classes in the system increases exponentially, which not only increases the complexity of the system to a certain extent, but also increases the dependence of the specific classes of the system. This is not a good thing.

Each product corresponds to a factory class, and then products of the same class, such as fruit classes, abstract a fruit factory, and the specific factory class implements its create method

MyDemo

image.png

Fruit interface

package com.melo.mydesign.Factory.FactoryMethod.Product;

//Products only care about use, not creation
public interface Fruit {
    void eat();
}

Specific subclasses of fruits

package com.melo.mydesign.Factory.FactoryMethod.Product;

public class Apple implements Fruit {
    @Override
    public void eat() {
        System. out. Println ("eat apples");
    }
}
package com.melo.mydesign.Factory.FactoryMethod.Product;

public class Pear implements Fruit {

    @Override
    public void eat() {
        System. out. Println ("eat pears");
    }
}

Fruit factory interface

package com.melo.mydesign.Factory.FactoryMethod.Factory;

import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;

public interface FruitFactory {
    Fruit createFruit();
}

Specific fruit factory implementation subclass

package com.melo.mydesign.Factory.FactoryMethod.Factory;

import com.melo.mydesign.Factory.FactoryMethod.Product.Apple;
import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;

public class AppleFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Apple();
    }
}
package com.melo.mydesign.Factory.FactoryMethod.Factory;

import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;
import com.melo.mydesign.Factory.FactoryMethod.Product.Pear;

public class PearFactory implements FruitFactory {
    @Override
    public Fruit createFruit() {
        return new Pear();
    }
}

Specific use

package com.melo.mydesign.Factory.FactoryMethod;

import com.melo.mydesign.Factory.FactoryMethod.Factory.AppleFactory;
import com.melo.mydesign.Factory.FactoryMethod.Factory.FruitFactory;
import com.melo.mydesign.Factory.FactoryMethod.Product.Fruit;

public class Consumer {

    public static void main(String[] args) {
        //The user does not need to know which class is in production, but faces the fruitfactory interface
        FruitFactory appleFactory = new AppleFactory();
        Fruit apple = appleFactory.createFruit();
        apple.eat();
    }

}

Abstract factory pattern

  • Factory method mode, with more and more products, more and more product categories and product factories will be produced. Can we separate a category of products and turn them into a product family?

This means that each product no longer corresponds to a product factory
It is a kind of product, corresponding to a product factory

image.png
Take rookie’s as an example (it feels more authoritative)

UML

  • First of all, from the perspective of users, to produce a product, you must first find the product at the beginningProduct categoryfactory

How to find product factories? Equivalent to product factories, they also need someone to create themHandling multiple productsWe call it factoryproducer

  • Then when you get the specific product factory, you need to produce specific products. The treatment method is the same as if else
    • The rest are products and parent products. See the following for the specific implementation code

image.png

You can see that the shape factory is responsible for multiple shapes, so you can return to a simple factory. One factory handles multiple products (you need to pass the string name and then if else)

Abstract factory and concrete product class factory (note that the methods of the factory class need to be defined)

The specific implementation depends on the subclass

  • You can see the shape product factory,You also have to implement the color methodIt’s just return null

image.png

At the same time, factoryproducer has to process multiple, both shape and color

Specific use

image.png

MyDemo

image.png

Abstract product factory

package com.melo.mydesign.Factory.AbstractFactory.Factory;

import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;

public interface AbstractFactory {
    Fruit createFruit(String fruitName);

    Car createCar(String carName);
}

Specific product factory – car

package com.melo.mydesign.Factory.AbstractFactory.Factory;

import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Audi;
import com.melo.mydesign.Factory.AbstractFactory.Product.Car.BMW;
import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;


public class CarFactory implements AbstractFactory{
    @Override
    public Fruit createFruit(String fruitName) {
        return null;
    }

    public Car createCar(String carName){
        if(carName.equalsIgnoreCase("BMW")){
            return new BMW();
        }else if(carName.equalsIgnoreCase("Audi")) {
            return new Audi();
        }
        return null;
    }
}

Specific product factory — fruit

package com.melo.mydesign.Factory.AbstractFactory.Factory;

import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Pear;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Apple;
import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;

public class FruitFactory implements AbstractFactory {
    public Fruit createFruit(String fruitName){
        if(fruitName.equalsIgnoreCase("Apple")){
            return new Apple();
        }else if(fruitName.equalsIgnoreCase("Pear")) {
            return new Pear();
        }
        return null;
    }

    @Override
    public Car createCar(String carName) {
        return null;
    }
}

Factoryproducer — the object of the factory responsible for producing products

package com.melo.mydesign.Factory.AbstractFactory.Factory;

public class FactoryProducer {

    public static AbstractFactory produceFactory(String factoryName){
        if(factoryName.equalsIgnoreCase("Fruit")){
            return new FruitFactory();
        }else if (factoryName.equalsIgnoreCase("Car")){
            return new CarFactory();
        }
        return null;
    }
}

Car product interface

package com.melo.mydesign.Factory.AbstractFactory.Product.Car;

//Products only care about use, not creation
public interface Car {
    void eat();
}

Car product realization

package com.melo.mydesign.Factory.AbstractFactory.Product.Car;

public class BMW implements Car {
    @Override
    public void eat() {
        System. out. Println ("BMW");
    }
}

Fruit products

package com.melo.mydesign.Factory.AbstractFactory.Product.Fruit;

//Products only care about use, not creation
public interface Fruit {
    void eat();
}

Fruit class implementation class

package com.melo.mydesign.Factory.AbstractFactory.Product.Fruit;


import com.melo.mydesign.Factory.AbstractFactory.Product.Fruit.Fruit;

public class Pear implements Fruit {

    @Override
    public void eat() {
        System. out. Println ("eat pears");
    }
}

consumer

package com.melo.mydesign.Factory.AbstractFactory;

import com.melo.mydesign.Factory.AbstractFactory.Factory.AbstractFactory;
import com.melo.mydesign.Factory.AbstractFactory.Factory.FactoryProducer;
import com.melo.mydesign.Factory.AbstractFactory.Product.Car.Car;

public class Consumer {
    public static void main(String[] args) {
        AbstractFactory carFactory = FactoryProducer.produceFactory("Car");
        Car bmw = null;
        if (carFactory != null) {
            bmw = carFactory.createCar("BMW");
        }
        if (bmw != null) {
            bmw.eat();
        }
    }
}

shortcoming

  • It no longer complies with the opening and closing principle, because the essence is upgraded from a simple factory and returned to a product factory. It needs to deal with the problems of multiple products, * * it needs if else **

summary

  • For a small factory model, the principles learned earlier are: opening and closing principle, relying on Inversion Principle (make good use of it)Abstract interfaceInstead of concrete realization), it is reflected incisively and vividly
    • Once there are more products, it is necessary to pull out an abstract product class interface and let subclasses implement it. Users only care about abstraction, not specific implementation, and do not need to know the specific class name. If they want to generate an apple, they can directly fruit apple = new apple(); Instead of apple apple = new apple();
    • If the production process becomes complicated, for example, apple still needs various treatments, the created process needs to be encapsulated and not exposed to users. At this time, a special factory class needs to be used for packaging. The outside world only needs to take it from the factory,Pass a simple “apple” string, which evolves into a simple factory mode
  • Then we found a simple factory class called simple, but it has to deal with a variety of products. Each time a new product is added, we have to modify the if else code block, which does not comply with the opening and closing principle
    • This introducesFactory method modelLet each product correspond to a product factory, a special factory to produce products. A factory is only responsible for the generation of one product, which meets the principle of single responsibility. At the same time, each new product only needs to add one more product factory. There is no need to modify the original factory, and the problem of opening and closing principle is solved
  • However, with the increasing number of products, if only one factory is responsible for one product, the number of factories may be more and more. Moreover, these products may have some connections before, such as fruits. Why don’t we pull out a fruit factory to produce all kinds of fruits

Careful readers may find that a factory has to be responsible for producing multiple products, which seems to return to the simple factory mode, which does not comply with the opening and closing principle and single responsibility. Yes,Abstract factory patternActuallySimple factoryJust an upgraded version of!


Author: “Melo ~”
source:https://www.cnblogs.com/melojun/
The copyright of this article belongs to the author and the blog park. Reprint is welcome, but this statement must be retained without the consent of the author, and the original link must be given in an obvious position on the article page, otherwise the right to investigate legal responsibility is reserved.

Recommended Today

The whole tutorial of docker installation and use, installation / complete command / dockerfile image production / docker container arrangement and one click installation of nginx + redis + MySQL / visualizer portal (version 2022)

官网: https://docs.docker.com/ 官网: https://www.docker.com/ docker 镜像市场: https://hub.docker.com/ 一、docker 说明 1.1、docker 核心 1、Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源,Docker 是一个 CS 架构软件。 2、Docker 是一个虚拟化轻量级linux服务器,可以解决我们在开发环境中运行配置问题 3.、Docker的主要目标是‘build ,ship and run any app,anywhere’,一次封装,到处运行 4、容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。 1.2、docker 版本问题 .Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。 1.3、docker 架构( 3大核心) · 1、Images 镜像 (等于软件) · 2、Registry […]