This is the 14th day of my participation in Gwen Challenge

JAVA Design Pattern family — Factory Pattern

Software Design Pattern, also known as Design Pattern, is a set of repeatedly used, most people know, after classification and cataloging, code Design experience summary. It describes some recurring problems in the software design process, and the solutions to this problem.

That is to say, it is a series of routines to solve a specific problem. It is a summary of the code design experience of predecessors. It has a certain universality and can be used repeatedly.

The goal is to improve code reusability, code readability, and code reliability.

So today we’re going to look at the factory method pattern, the second factory pattern in the design pattern.

In real life, the division of labor is becoming more and more detailed and more specialized, and all kinds of products are produced in specialized factories, which completely bid farewell to the age of self-sufficient small-scale peasant economy, which greatly reduces the production cycle of products and improves the production efficiency. So can we separate the production and use of software objects in software development? This requires the factory pattern in our design pattern.

First of all, let’s recall that the society has changed from the self-sufficiency primitive society at the beginning, to the farming workshop era, to the assembly line of the industrial revolution, and then to the modern industrial chain OEM. We will find that the production efficiency is getting higher and higher. In fact, the progress of the whole society is the epitome of the development of the factory model. Self-sufficiency started with no factories; To the small workshop to simply complete the production of goods, for the simple factory mode; To the industrial revolution assembly line, goods to complete self-production and self-marketing, for the factory method mode; To the current industrial chain OEM, such as foxconn and other enterprises, for other enterprises to provide factory assembly line, abstract factory model.

What is the factory model?

Define a factory interface to create product objects, deferring the actual creation of product objects to the concrete subfactory class. This satisfies the “create and use separation” characteristic required in the creative pattern. So wherever we need to generate complex objects in real development, we can try to consider using the factory pattern instead. According to the actual business scenarios, there are three different implementation modes of factory mode, namely simple factory mode, factory method mode and abstract factory mode.

So let’s take a look at each of these factory patterns in turn according to different scenarios.

Simple Factory model

We call the objects being created “products” and the objects creating the products “factories.” If you want to create a small number of products, you can do it with a single factory class, which is called the “simple Factory pattern”.

The method for creating an instance in a simple factory pattern is usually static

Therefore, Simple Factory Pattern is also called Static Factory Method Pattern.

First let’s look at the composition of the simple factory pattern:

  • SimpleFactory: is the core of the SimpleFactory pattern and is responsible for implementing the internal logic that creates all instances. The method of creating a product class for a factory class can be called directly from the outside world to create the desired product object.

  • Abstract Product: Is the parent of all objects created by a simple factory and is responsible for describing the common interface shared by all instances.

  • Concrete Products: Are the creation targets of the simple factory pattern.

The structure diagram is as follows:

What if we expressed it in Java code?

/ * * *@author hz
 * @version1.0 * /
public class Client {
    // Abstract product
    public interface Product {
        void show(a);
    }
    // Specific product: ProductA
    static class ConcreteProduct1 implements Product {
        public void show(a) {
            System.out.println("Specific product 1 shows..."); }}// Specific product: ProductB
    static class ConcreteProduct2 implements Product {
        public void show(a) {
            System.out.println("Specific product 2 shows..."); }}final class Const {
        static final int PRODUCT_A = 0;
        static final int PRODUCT_B = 1;
        static final int PRODUCT_C = 2;
    }
    static class SimpleFactory {
        public static Product makeProduct(int kind) {
            switch (kind) {
                case Const.PRODUCT_A:
                    return new ConcreteProduct1();
                case Const.PRODUCT_B:
                    return new ConcreteProduct2();
            }
            return null; }}}Copy the code

What are the pros and cons of this model?

Advantages:
  1. The factory class contains the logical judgment necessary to determine which instance of a product to create and when. The client can be relieved of the responsibility of creating product objects directly, making it easy to create corresponding products. The responsibilities of plant and product are clearly differentiated.
  2. The client does not need to know the class name of the specific product being created, just the parameters.
  3. Configuration files can also be introduced to replace and add new concrete product classes without modifying the client code.
Disadvantages:
  1. The simple factory mode has a single factory class, which is responsible for the creation of all products. The responsibility is too heavy. Once an exception occurs, the whole system will be affected. And the factory class code will be very bloated, against the principle of high aggregation.
  2. Using the simple factory pattern increases the number of classes in the system (introducing new factory classes), increasing the complexity and difficulty of understanding the system
  3. It is difficult to expand the system. Once a new product is added, the factory logic has to be modified. The logic may be too complicated when there are many product types
  4. The simple factory pattern uses the static factory approach, which prevents the factory roles from forming an inheritance-based hierarchy.

But simple factory pattern each adding a product to add a specific product class and a corresponding specific factory class, which has increased the complexity of the system, has violated the “open closed principle” * * * *, so we further to the abstract of simple factory, this also is behind us now will give you said the second implementation scenario factory pattern, factory method pattern.

Factory method pattern

Previously, we said that the simple factory pattern violates the open-closed principle, and the “factory method pattern” is a further abstraction of the simple factory pattern. Its advantage is that the system can introduce new products without modifying the original code, that is, meet the open-closed principle.

The main roles of the factory method pattern include:

  • Abstract Factory: Provides an interface for creating products through which callers create products by accessing the Factory method newProduct() of a concrete Factory.
  • ConcreteFactory: Abstract methods in abstract factories are implemented to create concrete products.
  • Abstract Product: Defines the specification of the Product, describing the main features and functions of the Product.
  • Concreteproducts: Interfaces that implement abstract product roles are created by concrete factories and correspond to concrete factories.

The structure diagram is as follows:

Compared with the simple factory mode, the factory method mode splits the factory into abstract factory and concrete factory on the basis of the simple factory, which greatly improves the flexibility.

Where can we use this model?

  • Users only need to know the name of the specific factory to get the product they want, without knowing the specific creation process of the product.
  • Increased flexibility, for the creation of new products, only need to write a corresponding factory class.
  • A typical decoupling framework. A high-level module only needs to know the abstract class of the product and does not need to care about other implementation classes, satisfying Demeter’s law, dependency inversion principle and Richter’s substitution principle.

What if we expressed it in Java code?

/ * * *@author hz
 * @version1.0 * /
public class AbstractFactoryTest {
    public static void main(String[] args) {
        try {
            Product a;
            AbstractFactory af;
            af = (AbstractFactory) ReadXML.getObject();
            // The abstract factory content is put into external configuration files such as XML /properties and is loaded through I/O streams to create the abstract factory
            a = af.newProduct();
            a.show();
        } catch(Exception e) { System.out.println(e.getMessage()); }}}// Abstract product: Provides an interface to the product
interface Product {
    public void show(a);
}
Concrete product 1: Implements abstract methods in abstract products
class ConcreteProduct1 implements Product {
    public void show(a) {
        System.out.println("Specific product 1 shows..."); }}Concrete product 2: Implements abstract methods in abstract products
class ConcreteProduct2 implements Product {
    public void show(a) {
        System.out.println("Specific product 2 shows..."); }}// Abstract factory: provides a method to generate factory goods
interface AbstractFactory {
    public Product newProduct(a);
}
// Factory 1: implementation of factory product generation method
class ConcreteFactory1 implements AbstractFactory {
    public Product newProduct(a) {
        System.out.println("Specific plant 1 generates --> Specific product 1...");
        return newConcreteProduct1(); }}// Factory 2: implementation of factory product generation method
class ConcreteFactory2 implements AbstractFactory {
    public Product newProduct(a) {
        System.out.println("Specific factory 2 generated --> Specific product 2...");
        return newConcreteProduct2(); }}Copy the code
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;
/ * * *@author hz
 * @version1.0 * /
public class ReadXML {
    // This method is used to extract the concrete class name from the XML configuration file and return an instance object
    public static Object getObject(a) {
        try {
            // Create a document object
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("src/FactoryMethod/config1.xml"));
            // Get the text node containing the class name
            NodeList nl = doc.getElementsByTagName("className");
            Node classNode = nl.item(0).getFirstChild();
            String cName = "FactoryMethod." + classNode.getNodeValue();
            // system.out. println(" new class name: "+cName);
            // Generate instance objects from the class name and return themClass<? > c = Class.forName(cName); Object obj = c.newInstance();return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null; }}}Copy the code

So what are the pros and cons of this model?

Advantages:
  • Users only need to know the name of the specific factory to get the product they want, without knowing the specific creation process of the product.
  • Increased flexibility, for the creation of new products, only need to write a corresponding factory class.
  • A typical decoupling framework. A high-level module only needs to know the abstract class of the product and does not need to care about other implementation classes, satisfying Demeter’s law, dependency inversion principle and Richter’s substitution principle.
Disadvantages:
  • It is easy to have too many classes and add complexity
  • The system is abstract and difficult to understand
  • Abstract products can only produce one product, which can be solved by using the abstract factory model.

Conclusion:

For a relatively small number of products, consider using the simple factory pattern. Clients using the simple factory pattern simply pass in the parameters of the factory class without worrying about the logic of how to create the object and can easily create the desired product.

For a product, the caller clearly knows which specific factory service should be used to instantiate the specific factory to produce the specific product. Then we can use the factory method pattern, such as the Iterator () method in JAVA Colletion.

Or we just need a product, but don’t want to know also don’t need to know exactly which factory for the production, the producers choose which concrete factory final call on one side, they are based on the current system to instantiate a concrete factory is returned to the user, and the decision-making process that is transparent for users, We can also choose the factory method model.

Note, however, that you can remove the abstract factory class when the number of products that need to be generated is small and does not increase, and a concrete factory class will do the job. At this point the factory method pattern degrades to the simple factory pattern.

Both the simple factory pattern and our factory method pattern consider a series of products of the same type. If the product type produced is not one type, how do we deal with it? This requires another pattern of our factory pattern, the Abstract factory pattern.