Factory method model of design pattern learning

Factory method pattern

Define an interface for creating objects, but let the subclass decide which class to instantiate. The factory method pattern delays the instantiation of a class to the subclass. It is a class creation mode

Class Diagram

Insert picture description here

achieve

Abstract factory

package design.factory;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public interface Factory {
    
    

    public Product factoryMethod();
}

Abstract product

package design.factory;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public interface Product {
    
    
}

Specific products

package design.factory;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class ConcreteProduct implements Product {
    
    
}

Specific factory

package design.factory;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class ConcreteFactory implements Factory {
    
    
    public Product factoryMethod(){
    
    
        return new ConcreteProduct();
    }
}

Client

package design.factory;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Factory factory;
        //可通过配置文件与反射机制实现
        factory=new ConcreteFactory();
        Product product;
        product=factory.factoryMethod();
    }
}

Applications

A system running log logger (Logger) can save the running log of the system in a variety of ways, such as file recording or database recording. The user can flexibly change the log recording method by modifying the configuration file. When designing various types of loggers, the developers found that some initialization work was required for the logger. The initialization parameter setting process is more complicated, and some parameters are set in strict order, otherwise recording failure may occur.
In order to better encapsulate the initialization process of the recorder and ensure the flexibility of switching between multiple recorders, the system is now designed using the factory method pattern. Note: The implementation of the writeLog() method only writes simple output statements.
Insert picture description here

Code

Abstract product

package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public interface Logger {
    
    
    public void writeLog();
}


Specific products

package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class DatabaseLogger implements Logger {
    
    

    public void writeLog() {
    
    
        System.out.println("数据库日志记录");

    }
}


package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class FileLogger implements Logger {
    
    

    public void writeLog() {
    
    
        System.out.println("文件日志记录");

    }
}


Abstract factory

package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public interface LoggerFactory {
    
    
    public Logger createLogger();
}

Specific factory

package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class DatabaseLoggerFactory implements LoggerFactory {
    
    

    public Logger createLogger() {
    
    
        Logger logger = new DatabaseLogger();
        return logger;
    }

}

package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class FileLoggerFactory implements LoggerFactory {
    
    

    public Logger createLogger() {
    
    
        Logger logger = new FileLogger();
        return logger;
    }
}


Client

package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        LoggerFactory factory;
        Logger logger;
        factory = new FileLoggerFactory();
        logger = factory.createLogger();
        logger.writeLog();
    }
}

There is a problem: if you need to replace the logger (specific factory class), you need to modify the client code, which does not meet the opening and closing principles

Solution: By introducing the configuration file and using the reflection mechanism to change the specific factory class without modifying the client code

Add config.xml configuration file

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<className>design.factory.test.FileLoggerFactory</className>
</config>

Add tools

package design.factory.test;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

public class XMLUtil {
    
    

	public static Object getBean() {
    
    
		try {
    
    
			// 创建DOM文档对象
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;
			doc = builder.parse(new File("src//design//factory//test//config.xml"));
			// 获取包含类名的文本节点
			NodeList nl = doc.getElementsByTagName("className");
			Node classNode = nl.item(0).getFirstChild();
			String cName = classNode.getNodeValue();

			// 通过类名生成实例对象
			Class c = Class.forName(cName);
			Object obj = c.newInstance();
			return obj;
		} catch (Exception e) {
    
    
			e.printStackTrace();
			return null;
		}
	}
}

The client code is

package design.factory.test;

/*
 *
 *@author:zzf
 *@time:2020-12-19
 *
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        LoggerFactory factory;
        Logger logger;
        //factory = new FileLoggerFactory();
        factory = (LoggerFactory) XMLUtil.getBean();
        logger = factory.createLogger();
        logger.writeLog();
    }
}

further optimization

Try to modify the factory base class to realize the transparency of the log family tree, that is, the client does not know any information of the log family tree (hint: use the factory method to hide)

Factory method hiding

Sometimes, in order to further simplify the use of the client, the factory method can also be hidden from the client. At this time, the business method of the product class is directly called in the factory class. The client does not need to call the factory method to create the product object. The factory object can be used to call all Business method in the created product object

Code

Change the abstract factory interface to an abstract class

public abstract class LoggerFactory {
    
    

	public void writeLog() {
    
    
		Logger logger = this.createLogger();
		logger.writeLog();
	}

	public abstract Logger createLogger();
}

Client code modification

public class Client {
    
    

	public static void main(String[] args) {
    
    
		LoggerFactory factory;
		factory = (LoggerFactory) XMLUtil.getBean();
		factory.writeLog();
	}
}

Advantages and disadvantages of the factory method pattern

Advantages:
(1) Provides a special factory method to create the products that customers need, and at the same time hides the details of which specific product category will be instantiated from the customer
(2) Based on the polymorphism of factory roles and product roles Design is the key to the factory method pattern . It allows the factory to independently determine which product object to create, and the details of how to create this object are completely encapsulated in the specific factory.
(3) When a new product is added to the system, the principle of opening and closing is fully complied with

Disadvantages:
(1) The number of classes in the system will increase in pairs, which will increase the complexity of the system to a certain extent, and will bring some additional overhead to
the system (2) Increase the abstraction and difficulty of understanding the system

Applicable environment

(1) The client does not know the class of the object it needs
(2) The abstract factory class specifies which object to create through its subclass

reference

Java design patterns

Guess you like

Origin blog.csdn.net/qq_43610675/article/details/111404590