Modelo de método de fábrica de aprendizaje de patrones de diseño

Patrón de método de fábrica

Defina una interfaz para crear objetos, pero deje que la subclase decida qué clase instanciar. El patrón del método de fábrica retrasa la instanciación de una clase a la subclase. Es un modo de creación de clases

Diagrama de clase

Inserte la descripción de la imagen aquí

lograr

Fábrica abstracta

package design.factory;

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

    public Product factoryMethod();
}

Producto abstracto

package design.factory;

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

Productos específicos

package design.factory;

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

Fábrica específica

package design.factory;

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

Cliente

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();
    }
}

Aplicaciones

Un registrador de registros en ejecución del sistema (Logger) puede guardar el registro en ejecución del sistema de diversas formas, como la grabación de archivos o la grabación de la base de datos. El usuario puede cambiar de forma flexible el método de grabación de registros modificando el archivo de configuración. Al diseñar varios tipos de registradores, los desarrolladores encontraron que se requería algo de trabajo de inicialización para el registrador. El proceso de configuración de parámetros de inicialización es más complicado y algunos parámetros se configuran en un orden estricto, de lo contrario pueden ocurrir fallas en la grabación.
Para encapsular mejor el proceso de inicialización del registrador y garantizar la flexibilidad de cambiar entre varios registradores, el sistema ahora está diseñado utilizando el patrón del método de fábrica. Nota: La implementación del método writeLog () solo escribe declaraciones de salida simples.
Inserte la descripción de la imagen aquí

Código

Producto abstracto

package design.factory.test;

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


Productos específicos

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("文件日志记录");

    }
}


Fábrica abstracta

package design.factory.test;

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

Fábrica específica

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;
    }
}


Cliente

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();
    }
}

Hay un problema: si necesita reemplazar el registrador (clase de fábrica específica), debe modificar el código del cliente, que no cumple con los principios de apertura y cierre

Solución: introduciendo el archivo de configuración y utilizando el mecanismo de reflexión para cambiar la clase de fábrica específica sin modificar el código del cliente

Agregar archivo de configuración config.xml

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

Agregar herramientas

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;
		}
	}
}

El código de cliente es

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();
    }
}

mayor optimización

Intente modificar la clase base de la fábrica para darse cuenta de la transparencia del árbol genealógico del registro, es decir, el cliente no conoce ninguna información del árbol genealógico del registro (pista: use el método de fábrica para ocultar)

Ocultación del método de fábrica

A veces, para simplificar aún más el uso del cliente, el método de fábrica también se puede ocultar al cliente. En este momento, el método comercial de la clase de producto se llama directamente en la clase de fábrica. El cliente no necesita llamar el método de fábrica para crear el objeto de producto. El objeto de fábrica se puede utilizar para llamar a todos los métodos de negocio en el objeto de producto creado

Código

Cambiar la interfaz de fábrica abstracta a una clase abstracta

public abstract class LoggerFactory {
    
    

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

	public abstract Logger createLogger();
}

Modificación del código del cliente

public class Client {
    
    

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

Ventajas y desventajas del patrón de método de fábrica.

Ventajas:
(1) Proporciona un método de fábrica especial para crear los productos que los clientes necesitan y, al mismo tiempo, oculta los detalles de qué categoría de producto específica se instanciará del cliente
(2) Basado en el polimorfismo de los roles de fábrica y los roles de producto El diseño es la clave del patrón del método de fábrica . Permite a la fábrica determinar de forma independiente qué objeto de producto crear, y los detalles de cómo crear este objeto están completamente encapsulados en la fábrica específica.
(3) Cuando se agrega un nuevo producto al sistema, el principio de apertura y cierre es totalmente cumplido con

Desventajas:
(1) El número de clases en el sistema aumentará en pares, lo que aumentará la complejidad del sistema hasta cierto punto y traerá algunos gastos generales adicionales al
sistema (2) Aumentará la abstracción y la dificultad de comprender la sistema

Entorno aplicable

(1) El cliente no conoce la clase del objeto que necesita
(2) La clase de fábrica abstracta especifica qué objeto crear a través de su subclase

referencia

Patrones de diseño de Java

Supongo que te gusta

Origin blog.csdn.net/qq_43610675/article/details/111404590
Recomendado
Clasificación