Patrón de fábrica abstracto
Proporcionar una interfaz para crear una serie de objetos relacionados o interdependientes sin especificar sus clases específicas. Es un modo de creación de objetos.
Diagrama de clase
AbstractProductA y AbstractProductB son dos productos abstractos
ConcreteProduct es la realización de la clasificación concreta de dos productos abstractos
AbstractFacroty es una interfaz de fábrica abstracta, que contiene todos los métodos abstractos para la creación de productos, y ConcreteFactory es una fábrica de hormigón.
Ejemplo de aplicación Una
empresa de software desea desarrollar un conjunto de biblioteca de máscaras de interfaz, que puede embellecer la interfaz del software de escritorio basado en Java. El usuario puede seleccionar la máscara a través del menú cuando lo usa. Diferentes máscaras proporcionarán botones, cuadros de texto, cuadros combinados y otros elementos de la interfaz con diferentes efectos visuales. Por ejemplo, una máscara de estilo Spring proporcionará botones de color verde claro y texto con bordes verdes . Un cuadro combinado con un cuadro y un borde verde, mientras que la máscara de estilo Verano proporciona un botón azul claro, un cuadro de texto con un borde azul y un cuadro combinado con un borde azul. El diagrama esquemático de la estructura se muestra en la siguiente figura:
La biblioteca de máscaras debe tener una buena flexibilidad y escalabilidad, los usuarios pueden elegir libremente diferentes máscaras y los desarrolladores pueden agregar nuevas máscaras sin modificar el código existente.
El patrón de fábrica abstracto ahora se usa para diseñar la biblioteca de máscaras de interfaz.
Código
Interfaz de botones, producto abstracto
package design.abstractfactory;
public interface Button {
public void display();
}
Productos específicos bajo la interfaz de botones
package design.abstractfactory;
public class SpringButton implements Button {
@Override
public void display() {
System.out.println("显示浅绿色按钮.");
}
}
package design.abstractfactory;
public class SummerButton implements Button {
@Override
public void display() {
System.out.println("显示浅蓝色按钮.");
}
}
Interfaz de cuadro de texto, producto abstracto
package design.abstractfactory;
public interface TextField {
public void display();
}
Productos específicos bajo la interfaz del cuadro de texto
package design.abstractfactory;
public class SpringTextField implements TextField {
@Override
public void display() {
System.out.println("显示绿色边框文本框.");
}
}
package design.abstractfactory;
public class SummerTextField implements TextField {
@Override
public void display() {
System.out.println("显示蓝色边框文本框.");
}
}
Interfaz de cuadro combinado, producto abstracto
package design.abstractfactory;
public interface ComboBox {
public void display();
}
Productos específicos bajo la interfaz del cuadro combinado
package design.abstractfactory;
public class SpringComboBox implements ComboBox {
@Override
public void display() {
System.out.println("显示绿色边框组合框.");
}
}
package design.abstractfactory;
public class SummerComboBox implements ComboBox {
@Override
public void display() {
System.out.println("显示蓝色边框组合框.");
}
}
Interfaz de interfaz de piel, que actúa como una fábrica abstracta.
package design.abstractfactory;
public interface SkinFactory {
public Button createButton();
public TextField createTextField();
public ComboBox createComboBox();
}
Fábrica específica
package design.abstractfactory;
public class SpringSkinFactory implements SkinFactory {
@Override
public Button createButton() {
return new SpringButton();
}
@Override
public TextField createTextField() {
return new SpringTextField();
}
@Override
public ComboBox createComboBox() {
return new SpringComboBox();
}
}
package design.abstractfactory;
public class SummerSkinFactory implements SkinFactory {
@Override
public Button createButton() {
return new SummerButton();
}
@Override
public TextField createTextField() {
return new SummerTextField();
}
@Override
public ComboBox createComboBox() {
return new SummerComboBox();
}
}
Archivo de configuración config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>design.abstractfactory.SpringSkinFactory</className>
</config>
Instrumentos
package design.abstractfactory;
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
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//abstractfactory//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;
}
}
}
Cliente
package design.abstractfactory;
public class Client {
public static void main(String[] args) {
// 使用抽象层定义
SkinFactory factory;
//SkinFactory factory1;
Button bt;
TextField tf;
ComboBox cb;
factory=(SkinFactory) XMLUtil.getBean();
bt=factory.createButton();
tf=factory.createTextField();
cb = factory.createComboBox();
bt.display();
tf.display();
cb.display();
}
}
Si necesita cambiar la máscara, simplemente modifique el archivo de configuración
Si hay un proyecto que necesita usar el cuadro de lista desplegable de estilo de primavera con el cuadro de texto y el botón de estilo de verano, cómo completarlo, intente lograrlo en el proyecto anterior
Agregar nueva clase de fábrica de concreto
package design.abstractfactory;
public class SpringSummerSkinFactory implements SkinFactory {
@Override
public Button createButton() {
return new SummerButton();
}
@Override
public TextField createTextField() {
return new SummerTextField();
}
@Override
public ComboBox createComboBox() {
return new SpringComboBox();
}
}
Reemplazar la referencia del archivo de configuración con la clase de fábrica
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>design.abstractfactory.SpringSummerSkinFactory</className>
</config>
El resultado de ejecutar el cliente es
Ventajas y desventajas del patrón de fábrica abstracto.
Ventajas :
(1) Aislar la generación de clases específicas, de modo que el cliente no necesite saber qué se crea
(2) Cuando se diseñan varios objetos en una familia de productos para trabajar juntos, se puede asegurar que el cliente siempre use solo el mismo Un objeto en una familia de productos
(3) Es conveniente agregar una nueva familia de productos, no es necesario modificar el sistema existente, de acuerdo con el principio de apertura y cierre
Desventajas : Es
problemático agregar una nueva estructura jerárquica, es necesario realizar cambios importantes en el sistema original e incluso es necesario modificar el código de la capa abstracta, lo que viola el principio de apertura y cierre.
Entorno aplicable
(1) Un sistema no debe depender de los detalles de cómo se crean, combinan y expresan las instancias de clases de productos
(2) Hay más de una familia de productos en el sistema, y solo se usa una familia de productos cada vez
(3) pertenece al mismo producto Los productos de la familia se utilizarán juntos. Esta restricción debe reflejarse en el diseño del sistema.
(4) La estructura de nivel de producto es estable. Una vez completado el diseño, no se agregará una nueva estructura de nivel de producto al sistema o la estructura de nivel de producto existente no se eliminará.
Comparación entre el método de fábrica y la fábrica abstracta
El método de fábrica generalmente solo produce un tipo de producto. El núcleo es definir métodos abstractos para crear productos específicos a través de subclases. Diferentes subclases producen diferentes productos; la fábrica abstracta produce un conjunto de productos, y cada subclase de fábrica necesita producir un conjunto de productos., Y cada producto tiene un tipo de concreto diferente en cada subcategoría; el
método de fábrica acecha en la fábrica abstracta. Esto tiene sentido, porque la tarea de la fábrica abstracta es definir la interfaz responsable de crear un conjunto de productos, y cada método de esta interfaz es responsable de crear un producto específico, así que deje que las subclases de la fábrica implementen estos métodos. Por ejemplo, para SkinFactory, si solo miramos un tipo de componente: botón, el método createButton () se define en la interfaz de fábrica, y la subclase implementa este método para crear botones de diferentes estilos, es decir, "la subclase decide qué instanciar Cuál es la clase ", se ajusta plenamente a la definición del método de fábrica.
Rendimiento específico : el método de fábrica tiene solo un método abstracto y la fábrica abstracta tiene una gran interfaz (o múltiples métodos abstractos);
Puntos comunes : el
principio de inversión de dependencia: todos se basan en la abstracción, no en las clases concretas,
explosión de clases: especialmente en las fábricas abstractas, lo que aumentará significativamente el número de clases;
Escenarios aplicables :
Abstract Factory: es aplicable cuando necesita crear una familia de productos y desea que los productos relacionados se fabriquen juntos.
Método de fábrica: al crear un producto, alternativamente, puede desacoplar el código de su cliente de las clases concretas que deben instanciarse, o puede usarlo si no sabe qué clases deben instanciarse en el futuro.
Pequeño resumen
Ya sea un patrón de fábrica simple, un patrón de método de fábrica o un patrón de fábrica abstracto, todos pertenecen al patrón de fábrica y son muy similares en forma y características. Su objetivo final es desacoplar.
Consulte el
patrón de diseño de Java
Pepitas: https://juejin.cn/post/6844903783680442381
Pepitas: https://juejin.cn/post/6844903895760650254