Patrones de diseño_Patrones creativos-《Patrones de fábrica》

Patrones de diseño_Patrones creativos-《Patrones de fábrica》

Las notas están organizadas a partir de la explicación detallada de los patrones de diseño de Java por programadores de caballos oscuros, 23 patrones de diseño de Java (diagrama + análisis de código fuente del marco + combate real)

descripción general

Requisitos: Diseñar un sistema de pedidos de cafetería.

  • Diseñe una clase de café (Coffee) y defina sus dos subclases (American Coffee [AmericanCoffee] y Latte Coffee [LatteCoffee]);
  • Luego diseñe una clase de cafetería (CoffeeStore), la cafetería tiene la función de pedir café.

Las clases específicas están diseñadas de la siguiente manera:

En java, todo es un objeto, y estos objetos necesitan ser creados. Si directamente nuevos el objeto cuando lo creas, el objeto estará severamente acoplado. Si queremos reemplazar el objeto, todos los lugares del nuevo objeto necesitan ser modificado, lo que obviamente viola el principio abierto-cerrado del diseño de software. Si usamos la fábrica para producir objetos, solo podemos tratar con la fábrica y desacoplarnos completamente del objeto.Si queremos reemplazar el objeto, podemos reemplazar directamente el objeto en la fábrica, logrando el propósito de desacoplarnos del objeto; entonces, la mayor ventaja de Factory Pattern es: desacoplamiento .

En este tutorial, se presentará el uso de tres fábricas:

  • Patrón de fábrica simple (23 patrones de diseño clásico que no pertenecen a GOF)
  • patrón de método de fábrica
  • patrón de fábrica abstracto

Patrón de fábrica simple

Simple Factory no es un patrón de diseño, sino más bien un hábito de programación.

estructura

Una fábrica simple contiene los siguientes roles:

  • Producto abstracto: define la especificación del producto y describe las principales características y funciones del producto.
  • Productos concretos: implementar o heredar subclases de productos abstractos
  • Fábrica de hormigón: Proporciona un método para crear un producto, y la persona que llama obtiene el producto a través de este método.

lograr

Ahora use una fábrica simple para mejorar el caso anterior, el diagrama de clases es el siguiente:

  • El código de clase de fábrica es el siguiente:

    /**
     * 简单咖啡工厂类,用来生产咖啡
     */
    public class SimpleCoffeeFactory {
          
          
    
        public Coffee createCoffee(String type) {
          
          
            Coffee coffee = null;
            if ("americano".equals(type)) {
          
          
                coffee = new AmericanoCoffee();
            } else if ("latte".equals(type)) {
          
          
                coffee = new LatteCoffee();
            }
            return coffee;
        }
    }
    
  • Categoría de cafetería:

    public class CoffeeStore {
          
          
    
        public Coffee orderCoffee(String type) {
          
          
    		// 创建简单工厂
            SimpleCoffeeFactory factory = new SimpleCoffeeFactory();
            // 调用生产咖啡的方法
            Coffee coffee = factory.createCoffee(type);
    
            // 加配料
            coffee.addMilk();
            coffee.addsugar();
    
            return coffee;
        }
    }
    

La fábrica maneja los detalles de la creación del objeto. Una vez que existe SimpleCoffeeFactory, orderCoffee() en la clase CoffeeStore se convierte en el cliente de este objeto. Si necesita el objeto Coffee más tarde, puede obtenerlo directamente de la fábrica. De esta forma se libera el acoplamiento con la clase de implementación Coffee, y al mismo tiempo se generan nuevos acoplamientos, el acoplamiento entre el objeto CoffeeStore y el objeto factory SimpleCoffeeFactory, y el acoplamiento entre el objeto factory y el objeto commodities.

Si agregamos nuevas variedades de café más tarde, definitivamente necesitaremos modificar el código de SimpleCoffeeFactory, lo que viola el principio de apertura y cierre. Puede haber muchos clientes de la clase de fábrica, como crear Meituan Waimai, etc. De esta manera, solo se debe modificar el código de la clase de fábrica y se omiten otras operaciones de modificación.

Ventajas y desventajas

ventaja

  • El proceso de creación de un objeto está encapsulado y el objeto se puede obtener directamente a través de parámetros. Separe la creación de objetos de la capa de lógica de negocios, para evitar modificar el código del cliente en el futuro.Si desea implementar un nuevo producto, puede modificar directamente la clase de fábrica sin modificar el código original, lo que reduce la posibilidad de que el cliente modificación de código y es más fácil expandir.

defecto

  • Al agregar nuevos productos, aún es necesario modificar el código de la clase de fábrica, lo que viola el "principio de abrir y cerrar".

expandir

fábrica estática

  • En desarrollo, algunas personas también definen la función de crear objetos en la clase de fábrica como estática.Este es el patrón de fábrica estático, y no es uno de los 23 patrones de diseño. el código se muestra a continuación:
public class SimpleCoffeeFactory {
    
    

    public static Coffee createCoffee(String type) {
    
    
        Coffee coffee = null;
        if ("americano".equals(type)) {
    
    
            coffee = new AmericanoCoffee();
        } else if("latte".equals(type)) {
    
    
            coffee = new LatteCoffee();
        }
        return coffe;
    }
}

patrón de método de fábrica

Para las deficiencias en el ejemplo anterior, usar el patrón del método de fábrica puede resolverlo perfectamente y seguir completamente el principio de apertura y cierre.

concepto

Defina una interfaz para crear objetos y deje que las subclases decidan qué objeto de clase de producto instanciar. Los métodos de fábrica difieren la instanciación de una clase de producto a sus subclases de fábrica.

estructura

El papel principal del patrón de método de fábrica:

  • Abstract Factory (Abstract Factory): proporciona una interfaz para crear productos, y la persona que llama la usa para acceder al método de fábrica de la fábrica específica para crear productos.
  • Concrete Factory (ConcreteFactory): Implementa principalmente el método abstracto en la fábrica abstracta para completar la creación de productos específicos.
  • Producto abstracto (Producto): define la especificación del producto y describe las principales características y funciones del producto.
  • Producto concreto (ConcreteProduct): implementa la interfaz definida por el rol de producto abstracto, y es creado por una fábrica específica, y corresponde a una fábrica específica uno a uno.

lograr

Use el patrón del método de fábrica para mejorar el ejemplo anterior, el diagrama de clases es el siguiente:

el código se muestra a continuación

  • Fábrica abstracta:

    public interface CoffeeFactory {
          
          
    	// 创建咖啡对象的方法 由具体的子类实现
        Coffee createCoffee();
    }
    
  • Fábrica específica:

    // 拿铁咖啡工厂,专门用来生产拿铁咖啡
    public class LatteCoffeeFactory implements CoffeeFactory {
          
          
    
        public Coffee createCoffee() {
          
          
            return new LatteCoffee();
        }
    }
    
    // 美式咖啡工厂,专门用来生产拿式咖啡
    public class AmericanCoffeeFactory implements CoffeeFactory {
          
          
    
        public Coffee createCoffee() {
          
          
            return new AmericanCoffee();
        }
    }
    
  • Categoría de cafetería:

    public class CoffeeStore {
          
          
    
        private CoffeeFactory factory;
    
        public CoffeeStore(CoffeeFactory factory) {
          
          
            this.factory = factory;
        }
    
        public Coffee orderCoffee() {
          
          
            Coffee coffee = factory.createCoffee();
            coffee.addMilk();
            coffee.addsugar();
            return coffee;
        }
    }
    

Del código escrito anteriormente, podemos ver que al agregar categorías de productos, las categorías de fábrica deben agregarse en consecuencia, y no es necesario modificar el código de la categoría de fábrica, lo que resuelve las deficiencias del modelo de fábrica simple.

El patrón del método de fábrica es una abstracción adicional del patrón de fábrica simple. Debido al uso del polimorfismo, el patrón del método de fábrica mantiene las ventajas del patrón de fábrica simple y supera sus deficiencias.

Ventajas y desventajas

ventaja

  • Los usuarios solo necesitan saber el nombre de la fábrica específica para obtener el producto que desean, sin conocer el proceso de creación específico del producto;
  • Al agregar nuevos productos al sistema, solo es necesario agregar categorías de productos específicas y categorías de fábrica específicas correspondientes, sin ninguna modificación a la fábrica original, y cumplir con el principio de apertura y cierre;

defecto

  • Cada vez que se agrega un producto, se debe agregar una categoría de producto específica y una categoría de fábrica específica correspondiente, lo que aumenta la complejidad del sistema.

patrón de fábrica abstracto

El modelo de método de fábrica presentado anteriormente considera la producción de un tipo de producto, como granjas de ganado que solo crían animales, fábricas de televisores que solo producen televisores y podcasts de Chuanzhi que solo capacitan a estudiantes que se especializan en software informático.

Estas fábricas solo producen el mismo tipo de productos, y el mismo tipo de productos se denominan productos del mismo nivel, es decir: el modelo del método de fábrica solo considera la producción de productos del mismo nivel, pero en la vida real, muchos Las fábricas son fábricas integrales que pueden producir múltiples niveles (tipos), por ejemplo, una fábrica de electrodomésticos produce televisores y lavadoras o acondicionadores de aire, y una universidad tiene especializaciones en software y biología.

El modelo abstracto de fábrica que se presentará en esta sección considerará la producción de productos de múltiples niveles. Un grupo de productos en diferentes niveles producidos por la misma fábrica específica se denomina familia de productos. El eje horizontal que se muestra en la siguiente figura es el producto nivel, es decir, la misma categoría de productos; el eje vertical es la familia de productos, es decir, los productos de la misma marca, y los productos de la misma marca se producen en la misma fábrica.

concepto

Es una estructura de patrón que proporciona una clase de acceso con una interfaz para crear un grupo de objetos relacionados o interdependientes, y la clase de acceso puede obtener diferentes niveles de productos de la misma familia sin especificar la clase específica del producto deseado.

El patrón de fábrica abstracto es una versión mejorada del patrón de método de fábrica. El patrón de método de fábrica solo produce un nivel de productos, mientras que el patrón de fábrica abstracto puede producir múltiples niveles de productos.

estructura

Las funciones principales del patrón de fábrica abstracto son las siguientes:

  • Abstract Factory (Abstract Factory): proporciona una interfaz para crear productos, que contiene múltiples métodos para crear productos y puede crear múltiples productos de diferentes niveles.
  • Concrete Factory: implementa principalmente múltiples métodos abstractos en la fábrica abstracta para completar la creación de productos específicos.
  • Producto abstracto (Producto): define la especificación del producto, describe las características y funciones principales del producto, y el patrón de fábrica abstracto tiene múltiples productos abstractos.
  • Producto concreto: implementa la interfaz definida por el rol de producto abstracto, y es creado por una fábrica específica.Tiene una relación de muchos a uno con la fábrica específica.

lograr

El negocio de cafetería actual ha cambiado, no solo para producir café sino también para producir postres, como tiramisú, mousse de matcha, etc. Si se utiliza el modelo de método de fábrica, es necesario definir tiramisú, mousse de matcha y fábricas de tiramisú, Las fábricas de mousse de matcha y las fábricas de postres son propensas a las explosiones. Entre ellos, el café con leche y el café americano son un grado de producto, ambos son café; el tiramisú y la mousse de matcha también son un grado de producto; el café con leche y el tiramisú son la misma familia de productos (es decir, ambos pertenecen al estilo italiano), Americano y el mousse de matcha son la misma familia de productos (es decir, ambos pertenecen al sabor americano). Entonces, este caso se puede implementar usando el patrón de fábrica abstracto. El diagrama de clases es el siguiente:

el código se muestra a continuación

  • Fábrica abstracta:

    public interface DessertFactory {
          
          
    
        Coffee createCoffee();
    
        Dessert createDessert();
    }
    
  • Fábrica específica:

    // 美式甜点工厂
    public class AmericanDessertFactory implements DessertFactory {
          
          
    
        public Coffee createCoffee() {
          
          
            return new AmericanCoffee();
        }
    
        public Dessert createDessert() {
          
          
            return new MatchaMousse();
        }
    }
    
    // 意大利风味甜点工厂
    public class ItalyDessertFactory implements DessertFactory {
          
          
    
        public Coffee createCoffee() {
          
          
            return new LatteCoffee();
        }
    
        public Dessert createDessert() {
          
          
            return new Tiramisu();
        }
    }
    

Si desea agregar la misma familia de productos, solo necesita agregar una clase de fábrica correspondiente y no necesita modificar otras clases.

Ventajas y desventajas

ventaja

  • Cuando se diseñan varios objetos en una familia de productos para trabajar juntos, se garantiza que los clientes siempre usen solo objetos de la misma familia de productos.

defecto

  • Cuando es necesario agregar un nuevo producto a la familia de productos, es necesario modificar todas las clases de fábrica. Esto es un poco una violación del principio de diseño de estar cerrado para modificación y abierto para extensión .

Escenas a utilizar

  • Cuando los objetos a crear son una serie de familias de productos interrelacionados o interdependientes, como televisores, lavadoras y acondicionadores de aire en fábricas de electrodomésticos.
  • Hay varias familias de productos en el sistema, pero solo se usa una de ellas a la vez. Por ejemplo, a alguien solo le gusta usar ropa y zapatos de cierta marca.
  • La biblioteca de clases de productos se proporciona en el sistema, y ​​todos los productos tienen la misma interfaz, y el cliente no depende de los detalles de creación y la estructura interna de la instancia del producto.

como:

  • Cambie la máscara del método de entrada y cambie todo el conjunto a la vez.
  • Generar programas para diferentes sistemas operativos.

extensión de esquema

Desacoplamiento simple de fábrica + archivo de configuración

El acoplamiento de objetos de fábrica y objetos de producto se puede desacoplar a través del patrón de fábrica + archivo de configuración. Cargue el nombre completo de la clase en el archivo de configuración en la clase de fábrica y cree un objeto para el almacenamiento.Si el cliente necesita el objeto, puede obtenerlo directamente.

  • Paso 1: Definir el archivo de configuración

    Para la conveniencia de la demostración, usamos el archivo de propiedades como el archivo de configuración, llamadobean.properties

    american=com.itheima.pattern.factory.config_factory.AmericanCoffee
    latte=com.itheima.pattern.factory.config_factory.LatteCoffee
    
  • Paso 2: mejora la clase de fábrica

    public class CoffeeFactory {
          
          
    
        /*
         * 加载配置文件,获取配置文件中配置的全类名,并创建该类的对象进行存储
         */
        // 1.定义容器对象存储咖啡对象
        private static Map<String, Coffee> map = new HashMap();
    
        // 2.加载配置文件,只需要加载一次
        static {
          
          
            // 2.1 创建Properties对象
            Properties p = new Properties();
            // 2.2 调用p对象中的load方法进行配置文件的加载
            InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            try {
          
          
                p.load(is);
                // 遍历Properties集合对象
                Set<Object> keys = p.keySet();
                for (Object key : keys) {
          
          
                    // 根据键获取值(全类名)
                    String className = p.getProperty((String) key);
                    // 获取字节码对象
                    Class clazz = Class.forName(className);
                    // 通过反射技术创建对象
                    Coffee obj = (Coffee) clazz.newInstance();
                    // 将名称和对象存储到容器中
                    map.put((String) key, obj);
                }
            } catch (Exception e) {
          
          
                e.printStackTrace();
            }
        }
    
        // 根据名称获取对象
        public static Coffee createCoffee(String name) {
          
          
            return map.get(name);
        }
    }
    

Las variables miembro estáticas se utilizan para almacenar objetos creados (la clave almacena el nombre y el valor almacena el objeto correspondiente), mientras que la lectura de archivos de configuración y la creación de objetos se escriben en bloques de código estático, por lo que solo deben ejecutarse una vez.

Análisis de código fuente de JDK: método Collection.iterator

public class Demo {
    
    
    public static void main(String[] args) {
    
    
        List<String> list = new ArrayList<>();
        list.add("令狐冲");
        list.add("风清扬");
        list.add("任我行");

        // 获取迭代器对象
        Iterator<String> it = list.iterator();
        // 使用迭代器遍历
        while(it.hasNext()) {
    
    
            String ele = it.next();
            System.out.println(ele);
        }
    }
}

Debe estar familiarizado con el código anterior, utilizando iteradores para recorrer la colección y obtener los elementos de la colección. El método para obtener iteradores para colecciones de una sola columna utiliza el patrón del método de fábrica . Veamos la estructura a través del diagrama de clases:

La interfaz Collection es una clase de fábrica abstracta, ArrayList es una clase de fábrica concreta; la interfaz Iterator es una clase de producto abstracta y la clase interna Itr en la clase ArrayList es una clase de producto concreta. En la clase de fábrica específica, el método iterator() crea un objeto de la clase de producto específica.

imagen-20230103150804515

Otro:

  • El método getInstance() en la clase DateFormt usa el patrón de fábrica;
  • El método getInstance() en la clase Calendar usa el patrón de fábrica;

Supongo que te gusta

Origin blog.csdn.net/weixin_53407527/article/details/128627789
Recomendado
Clasificación