La aplicación de varios modelos de fábrica.

La aplicación de varios modelos de fábrica.

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 del patrón de fábrica es: desacoplamiento .

1. Patrón de fábrica simple (no 23 patrones de diseño)

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

1.1 Estructura

  • 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.

2.2 Implementación

2.2.1 Diagrama de clase de fábrica simple

El método de fábrica simple maneja los detalles de la creación del objeto. Una vez que está disponible SimpleCoffeeFactory, el objeto CoffeeStore类en el medio orderCoffee()se convierte en el cliente de este objeto. Si necesita el objeto Café 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 genera un nuevo acoplamiento entre el objeto CoffeeStore y el objeto factory SimpleCoffeeFactory , y el acoplamiento entre el objeto factory y el objeto commodities . Además de las nuevas variedades de café , está obligado a necesitar modificar SimpleCoffeeFactoryel código, lo que viola el principio de apertura y cierre . Puede haber muchos clientes de la clase de fábrica. En este momento, solo se debe modificar el código de la clase de fábrica y se omiten otras operaciones de modificación.

inserte la descripción de la imagen aquí

2.2.2 Código

/**
 * 抽象产品:咖啡
 */
public abstract class Coffee {
    
    
    // 抽象方法获取子类的咖啡的名称
    public abstract String getName();
    // 加糖
    public void addSugar() {
    
    
        System.out.println("加糖");
    }
    // 加奶
    public void addMilk() {
    
    
        System.out.println("加奶");
    }
}

/**
 * 具体产品:美式咖啡
 */
public class AmericanCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "美式咖啡";
    }
}

/**
 * 具体产品:拿铁咖啡
 */
public class LatteCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "拿铁咖啡";
    }
}

/**
 * 具体工厂:简单咖啡工厂类,用来生产咖啡
 */
public class SimpleCoffeeFactory {
    
    
    public Coffee createCoffee(String coffeeType){
    
    
        // 声明Coffee类型的变量,根据不同类型创建不同的coffee子类对象
        Coffee coffee;
        if("american".equals(coffeeType)){
    
    
            coffee = new AmericanCoffee();
        }else if ("latte".equals(coffeeType)){
    
    
            coffee = new LatteCoffee();
        }else {
    
    
            throw new RuntimeException("sorry,本店没有出售此类咖啡");
        }
        return coffee;
    }
}

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

/**
 * 客户点咖啡
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        //创建咖啡店类对象
        CoffeeStore store = new CoffeeStore();
        Coffee coffee = store.orderCoffee("latte");
        System.out.println(coffee.getName());
    }
}

2.2.3 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".

2. Patrón de fábrica estático (no 23 patrones de diseño)

Defina 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.

3.1 Código

/**
 * 抽象产品:咖啡
 */
public abstract class Coffee {
    
    
    // 抽象方法获取子类的咖啡的名称
    public abstract String getName();
    // 加糖
    public void addSugar() {
    
    
        System.out.println("加糖");
    }
    // 加奶
    public void addMilk() {
    
    
        System.out.println("加奶");
    }
}

/**
 * 具体产品:美式咖啡
 */
public class AmericanCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "美式咖啡";
    }
}

/**
 * 具体产品:拿铁咖啡
 */
public class LatteCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "拿铁咖啡";
    }
}

/**
 * 具体工厂:简单咖啡工厂类,用来生产咖啡
 */
public class SimpleCoffeeFactory {
    
    
    // 静态方法
    public static Coffee createCoffee(String coffeeType){
    
    
        // 声明Coffee类型的变量,根据不同类型创建不同的coffee子类对象
        Coffee coffee;
        if("american".equals(coffeeType)){
    
    
            coffee = new AmericanCoffee();
        }else if ("latte".equals(coffeeType)){
    
    
            coffee = new LatteCoffee();
        }else {
    
    
            throw new RuntimeException("sorry,本店没有出售此类咖啡");
        }
        return coffee;
    }
}

/**
 * Coffee店
 */
public class CoffeeStore {
    
    
    public Coffee orderCoffee(String coffeeType){
    
    
        // 不需要创建简单工厂来提供生产咖啡的方法
        // 直接类调用静态方法调用生产咖啡的方法
        Coffee coffee = SimpleCoffeeFactory.createCoffee(coffeeType);
        // 加配料
        coffee.addSugar();
        coffee.addMilk();
        return coffee;
    }
}

/**
 * 客户点咖啡
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        //创建咖啡店类对象
        CoffeeStore store = new CoffeeStore();
        Coffee coffee = store.orderCoffee("latte");
        System.out.println(coffee.getName());
    }
}

3. Modo de fábrica

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 .

3.1 Estructura

  • 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.

3.2 Implementación

3.2.1 Diagrama de clase de patrón de fábrica

Al agregar categorías de productos, las categorías de fábrica también 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.

inserte la descripción de la imagen aquí

3.2.2 Código

/**
 * 抽象产品:咖啡
 */
public abstract class Coffee {
    
    
    // 抽象方法获取子类的咖啡的名称
    public abstract String getName();
    // 加糖
    public void addSugar() {
    
    
        System.out.println("加糖");
    }
    // 加奶
    public void addMilk() {
    
    
        System.out.println("加奶");
    }
}

/**
 * 具体产品:美式咖啡
 */
public class AmericanCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "美式咖啡";
    }
}

/**
 * 具体产品:拿铁咖啡
 */
public class LatteCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "拿铁咖啡";
    }
}

/**
 * 抽象工厂
 */
public interface CoffeeFactory {
    
    
    //创建咖啡对象的方法
    Coffee createCoffee();
}

/**
 * 美式咖啡工厂对象,专门用来生产美式咖啡
 */
public class AmericanCoffeeFactory implements CoffeeFactory {
    
    
    @Override
    public Coffee createCoffee() {
    
    
        return new AmericanCoffee();
    }
}

/**
 * 拿铁咖啡工厂,专门用来生产拿铁咖啡
 */
public class LatteCoffeeFactory implements CoffeeFactory{
    
    
    @Override
    public Coffee createCoffee() {
    
    
        return new LatteCoffee();
    }
}

/**
 * Coffee店
 */
public class CoffeeStore {
    
    
    private CoffeeFactory factory;
    public void setFactory(CoffeeFactory factory) {
    
    
        this.factory = factory;
    }
    //点咖啡功能
    public Coffee orderCoffee() {
    
    
        Coffee coffee = factory.createCoffee();
        //加配料
        coffee.addMilk();
        coffee.addsugar();
        return coffee;
    }
}

/**
 * 客户点咖啡
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        //创建咖啡店对象
        CoffeeStore store = new CoffeeStore();
        //创建对象
        //CoffeeFactory factory = new AmericanCoffeeFactory();
        CoffeeFactory factory = new LatteCoffeeFactory();
        store.setFactory(factory);
        //点咖啡
        Coffee coffee = store.orderCoffee();
        System.out.println(coffee.getName());
    }
}

3.2.3 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 .

4. Patrón de fábrica abstracto

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 . 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 .

4.1 Estructura

  • 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.

4.2 Implementación

4.2.1 Diagrama de clase de patrón de fábrica abstracto

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.

inserte la descripción de la imagen aquí

4.2.2 Código

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

/**
 * 抽象产品:咖啡
 */
public abstract class Coffee {
    
    
    // 抽象方法获取子类的咖啡的名称
    public abstract String getName();
    // 加糖
    public void addSugar() {
    
    
        System.out.println("加糖");
    }
    // 加奶
    public void addMilk() {
    
    
        System.out.println("加奶");
    }
}

/**
 * 具体产品:美式咖啡
 */
public class AmericanCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "美式咖啡";
    }
}

/**
 * 具体产品:拿铁咖啡
 */
public class LatteCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "拿铁咖啡";
    }
}

/**
 * 抽象产品:甜品
 */
public abstract class Dessert {
    
    
    public abstract void show();
}

/**
 * 具体产品:提拉米苏类
 */
public class Trimisu extends Dessert {
    
    
    public void show() {
    
    
        System.out.println("提拉米苏");
    }
}

/**
 * 具体产品:抹茶慕斯类
 */
public class MatchaMousse extends Dessert {
    
    
    public void show() {
    
    
        System.out.println("抹茶慕斯");
    }
}

/**
 * 抽象工厂: DessertFactory
 */
public interface DessertFactory {
    
    
    //生产咖啡的功能
    Coffee createCoffee();
    //生产甜品的功能
    Dessert createDessert();
}

/**
 * 美式风味的甜品工厂
 * 生产美式咖啡和抹茶慕斯
 */
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 Trimisu();
    }
}

/**
 * 客户类
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        //创建的是意大利风味甜品工厂对象
        //ItalyDessertFactory factory = new ItalyDessertFactory();
        //创建的是美式风味甜品工厂对象
        AmericanDessertFactory factory = new AmericanDessertFactory();
        //获取拿铁咖啡和提拉米苏甜品
        Coffee coffee = factory.createCoffee();
        Dessert dessert = factory.createDessert();
        System.out.println(coffee.getName());
        dessert.show();
    }
}

4.2.3 Ventajas y desventajas

ventaja:

Cuando se diseñan varios objetos en una familia de productos para que funcionen 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.

4.2.4 Escenarios de uso

  • 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.

5. Extensión de modo

Desacople el objeto de fábrica y el objeto de producto a través del modo 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.

5.1 Definir el archivo de configuración

Defina un archivo de configuración llamado bean.properties.

american=config_factory.AmericanCoffee
latte=config_factory.LatteCoffee

5.2 Código

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.

/**
 * 抽象产品:咖啡
 */
public abstract class Coffee {
    
    
    // 抽象方法获取子类的咖啡的名称
    public abstract String getName();
    // 加糖
    public void addSugar() {
    
    
        System.out.println("加糖");
    }
    // 加奶
    public void addMilk() {
    
    
        System.out.println("加奶");
    }
}

/**
 * 具体产品:美式咖啡
 */
public class AmericanCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "美式咖啡";
    }
}

/**
 * 具体产品:拿铁咖啡
 */
public class LatteCoffee extends Coffee {
    
    
    // 继承父类的方法,重写直接返回名称
    public String getName() {
    
    
        return "拿铁咖啡";
    }
}

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

/**
 * 客户类
 */
public class Client {
    
    
    public static void main(String[] args) {
    
    
        Coffee coffee = CoffeeFactory.createCoffee("american");
        System.out.println(coffee.getName());
    }
}

记录每一个学习瞬间

Supongo que te gusta

Origin blog.csdn.net/qq_51601665/article/details/131052702
Recomendado
Clasificación