Original design pattern series [17]: Factory Method Pattern

Posted by xeonman13 on Sat, 22 Jan 2022 04:32:36 +0100

In life, the social division of labor is becoming more and more detailed and professional. All kinds of products are produced in special factories, completely bidding farewell to the era of self-sufficient small-scale peasant economy, which greatly shortens the production cycle and improves the production efficiency. Similarly, can we separate the production and use of software objects in software development? Can customers add, delete or change the use of software related objects on the premise of meeting the "opening and closing principle"? This is the problem to be discussed in this section.

In< Simple factory mode >In the first section, we introduced the simple factory mode and mentioned that the simple Communist mode violates the opening and closing principle, and the "factory method mode" is a further abstraction of the simple factory mode. Its advantage is that the system can introduce new products without modifying the original code, that is, it meets the opening and closing principle.

advantage:

  • Users only need to know the name of the specific factory to get the desired product, without knowing the specific creation process of the product.
  • Flexibility is enhanced. For the creation of new products, you only need to thank a corresponding factory class.
  • Typical decoupling framework. The high-level module only needs to know the abstract class of the product, does not need to care about other implementation classes, and meets the Demeter rule, the dependency inversion principle and the Riemannian substitution principle.

Disadvantages:

  • The number of classes is easy to be too many, which increases the complexity
  • It increases the abstraction and understanding difficulty of the system
  • Abstract products can only produce one product, and secondary disadvantages can be solved by using abstract factory mode.

Application scenario:

  • The customer only knows the name of the factory that created the product, but does not know the specific product name. Such as TCL TV factory, Hisense TV factory, etc.
  • The task of creating objects is completed by one of multiple concrete sub factories, while the abstract factory only provides the interface to create products.
  • Customers don't care about the details of creating products, only about the brand of products.

Structure and implementation of pattern

The factory method pattern consists of four elements: abstract factory, concrete factory, abstract product and concrete product. This section analyzes its basic structure and implementation method.

1. Institutional model

The main roles of the factory method model are as follows:

  1. Abstract Factory: it provides an interface to create a product, through which the caller accesses the method newProduct() of a specific factory to create a product.
  2. Concrete factory: it mainly implements the abstract methods in the abstract factory and completes the creation of specific products.
  3. Abstract Product: defines the Product specification and describes the main features and functions of the Product.
  4. Concrete product: it implements the interface defined by the abstract product role, which is created by the specific factory and corresponds to the specific factory one by one.

Its structure is shown in Figure 1:

2. Implementation of mode

Write the code of this mode according to the above figure as follows:

package FactoryMethod;

public class AbstractFactoryTest {
    public static void main(String[] args) {
        try {
            Product a;
            AbstractFactory af;
            af = (AbstractFactory) ReadXML1.getObject();
            a = af.newProduct();
            a.show();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

//Abstract product: provides the interface of the product
interface Product {
    public void show();
}

//Concrete product 1: implement abstract methods in abstract products
class ConcreteProduct1 implements Product {
    public void show() {
        System.out.println("Specific product 1 display...");
    }
}

//Concrete product 2: implement abstract methods in abstract products
class ConcreteProduct2 implements Product {
    public void show() {
        System.out.println("Specific product 2 display...");
    }
}

//Abstract factory: provides the generation method of factory products
interface AbstractFactory {
    public Product newProduct();
}

//Specific factory 1: the generation method of factory products is realized
class ConcreteFactory1 implements AbstractFactory {
    public Product newProduct() {
        System.out.println("Specific factory 1 generation-->Specific products 1...");
        return new ConcreteProduct1();
    }
}

//Specific factory 2: the generation method of factory products is realized
class ConcreteFactory2 implements AbstractFactory {
    public Product newProduct() {
        System.out.println("Specific plant 2 generation-->Specific products 2...");
        return new ConcreteProduct2();
    }
}
package FactoryMethod;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import java.io.*;

class ReadXML1 {
    //This method is used to extract the specific class name from the XML configuration file and return an instance object
    public static Object getObject() {
        try {
            //Create document object
            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = dFactory.newDocumentBuilder();
            Document doc;
            doc = builder.parse(new File("src/FactoryMethod/config1.xml"));
            //Gets 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 an instance object from the class name and return it
            Class<?> c = Class.forName(cName);
            Object obj = c.newInstance();
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<config>
	<className>ConcreteFactory1</className>
</config>

The running results of the program are as follows:

Specific factory 1 generation-->Specific products 1...
Specific product 1 display...

If ConcreteFactory1 in the XML configuration file is changed to ConcreteFactory2, the program runs as follows:

Specific plant 2 generation-->Specific products 2...
Specific product 2 display...

Note: when there are few products to be generated and will not be added, and a specific factory class can complete the task, the abstract factory class can be deleted. At this point, the factory method pattern will degenerate to the simple factory pattern.

Topics: Design Pattern