Notas de patrón de diseño de Java -------- patrón de fábrica ------ patrón de fábrica abstracto

Patrón de fábrica abstracto

introducción básica

1) Se define una interfaz para crear un grupo de objetos relacionados o dependientes sin especificar la clase específica
2) El patrón de fábrica abstracto puede integrar el patrón de fábrica simple y el patrón de método de fábrica .
3) Desde una perspectiva de diseño , el patrón de fábrica abstracto es una mejora del patrón de fábrica simple (o llamado abstracción adicional).
4) La fábrica se abstrae en dos capas , AbsFactory (fábrica abstracta) y subclases de fábrica implementadas concretamente . El programador puede utilizar la subclase de fábrica correspondiente según el tipo de objeto creado . Esto convierte una sola clase de fábrica simple en un clúster de fábrica, que es más propicio para el mantenimiento y la expansión del código.

Diagrama de clase

El modelo de fábrica abstracto completa el proyecto de pizza
utilizando el diagrama de clases del Sr. Han de Shang Silicon Valley.
Inserte la descripción de la imagen aquí

La mejora es : Nuestra fábrica se divide en dos capas. Solía ​​haber pedidos en diferentes regiones, pero ahora es una fábrica en diferentes lugares, pero solo hay una clase de pedido. Los diferentes pedidos se completan mediante diferentes subclases de implementación de fábrica.

Código

Primero, nuestras 5 pizzas

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/21 20:06
 * @Description TODO
 * @pojectname 披萨抽象类    设置为抽象类
 */
public abstract class Pizza {
    
    
    //披萨名字
    protected String name;
    //抽象方法 准备原材料  不同的披萨,原材料是不同的
    //因此做成抽象方法
    public abstract void prepare();
    //其他方法,我们人为流程是差不多的所以就是普通方法
    public void bake(){
    
    
        System.out.println(name+"baking;");
    }

    public void cut(){
    
    
        System.out.println(name+"cutting;");
    }
    public void box(){
    
    
        System.out.println(name+"boxing");
    }

    public void setName(String name) {
    
    
        this.name = name;
    }
}
/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/25 20:47
 * @Description TODO
 * @pojectname 代码
 */
public class HNCheesePizza extends Pizza{
    
    
    @Override
    public void prepare() {
    
    
        setName("河南的奶酪披萨");
        System.out.println("给河南奶酪披萨准备原材料");
    }
}
/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/25 20:49
 * @Description TODO
 * @pojectname 代码
 */
public class HNPepperPizza extends  Pizza {
    
    
    @Override
    public void prepare() {
    
    
        setName("河南的胡椒披萨");
        System.out.println("给河南胡椒披萨准备原材料");
    }
}
/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/25 20:47
 * @Description TODO
 * @pojectname 代码
 */
public class LDCheesePizza extends Pizza{
    
    
    @Override
    public void prepare() {
    
    
        setName("伦敦的奶酪披萨");
        System.out.println("给伦敦奶酪披萨准备原材料");
    }
}
/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/25 20:47
 * @Description TODO
 * @pojectname 代码
 */
public class LDPepperPizza extends Pizza{
    
    
    @Override
    public void prepare() {
    
    
        setName("伦敦的胡椒披萨");
        System.out.println("给伦敦胡椒披萨准备原材料");
    }
}

¡Entonces estamos viendo nuestros cambios! ! !

Nuestro modelo de método de fábrica es que la clase de orden se convierte en una clase abstracta, y hay un método abstracto en ella. Este método abstracto es responsable de crear instancias de diferentes sabores en diferentes lugares, ¿verdad?

Veamos nuestro modelo de fábrica simple . Define una fábrica simple de SimpleFactory para permitirle crear objetos.

Entonces mira nuestro patrón de fábrica abstracto

Primero , define una interfaz de fábrica AbsFactory

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/26 12:18
 * @Description TODO
 * @pojectname 抽象工厂模式的抽象层(接口)
 */
public interface AbsFactory {
    
    
    //让下面的工厂子类具体实现创建什么种类的实例对象
    public Pizza createPizza(String orderType);
}

Que hay un método , se usa para crear diferentes gustos de diferentes pizzerías , que nuestra fábrica es simple para lograr su propia clase, el método de fábrica es crear una subclase, y ahora él es la interfaz, ¿Quién la creó?

Esas son las subcategorías de fábrica responsables de diferentes gustos en diferentes lugares: HNFactory y LDFactory

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/26 12:20
 * @Description TODO
 * @pojectname 河南工厂子类
 */
public class HNFactory implements AbsFactory {
    
    

    @Override
    public Pizza createPizza(String orderType) {
    
    
        System.out.println("使用的是抽象工厂模式");
        Pizza pizza = null;
        if (orderType.equals("cheese")){
    
    
            pizza = new HNCheesePizza();
        }else if (orderType.equals("pepper")){
    
    
            pizza = new HNPepperPizza();
        }
        return pizza;
    }
}
/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/26 12:20
 * @Description TODO
 * @pojectname 伦敦工厂子类
 */
public class LDFactory implements AbsFactory {
    
    

    @Override
    public Pizza createPizza(String orderType) {
    
    
        System.out.println("使用的是抽象工厂模式");
        Pizza pizza = null;
        if (orderType.equals("cheese")){
    
    
            pizza = new LDCheesePizza();
        }else if (orderType.equals("pepper")){
    
    
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

Entonces, ¿ qué hace nuestra categoría de pedido ? En el modelo de método de fábrica anterior , se creaban diferentes objetos de instancia en el pedido . Ahora este trabajo se entrega a la subclase de fábrica. ¿Qué hace el pedido?

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/26 12:26
 * @Description TODO
 * @pojectname 订单代码
 */
public class OrderPizza {
    
    
    AbsFactory factory;
    //构造器
    public OrderPizza(AbsFactory factory){
    
    
        setFactory(factory);
    }
    //通过接口依赖
    private void setFactory(AbsFactory factory){
    
    
        Pizza pizza = null;
        String orderType = "";//用户输入种类
        this.factory = factory;
        do {
    
    
            orderType = getType();
//            factory可能是北京的工厂子类,也可能是伦敦的工厂子类
            pizza = factory.createPizza(orderType);
            if (pizza!=null){
    
    
                 pizza.prepare();
                 pizza.bake();
                 pizza.cut();
                 pizza.box();
            }else {
    
    
                System.out.println("订购失败");
                break;
            }
        }while (true);
    }
    //获取客户订购的披萨种类
    private String getType(){
    
    
        try {
    
    
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza 种类:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
    
    
            e.printStackTrace();
            return "";
        }
    }

}

Descubrimos que el constructor de la clase de orden se pasó en un objeto de interfaz y que la interfaz no puede ser nueva, por lo que es equivalente a pasar una clase de implementación del objeto de interfaz, es decir, HNFactory o LDFactory . Es decir, cuando se inicializa la clase de pedido, ya tienes la fábrica de qué sabor en ese lugar . En el método setFactory de la clase de pedido, pizza obtiene el tipo de sabor y puedes obtener los objetos de instancia propios. sabor en diferentes fábricas! ! !

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/26 12:34
 * @Description TODO
 * @pojectname 代码
 */
public class PizzaStore {
    
    
    public static void main(String[] args) {
    
    

        new OrderPizza(new HNFactory());
    }
}

Hasta ahora, nuestro modelo de fábrica abstracto está completo.

Análisis y suplemento del código fuente

Por ejemplo java-util-Calendar class clase de calendario

import java.util.Calendar;

/**
 * @author 王庆华
 * @version 1.0
 * @date 2020/12/26 12:53
 * @Description TODO
 * @pojectname 工厂模式源码分析
 */
public class test {
    
    
    public static void main(String[] args) {
    
    
        Calendar cal  = Calendar.getInstance();
        System.out.println("年:"+cal.get(Calendar.YEAR));
        System.out.println("月:"+(cal.get(Calendar.MONTH)+1));
        System.out.println("日:"+cal.get(Calendar.DAY_OF_MONTH));
        System.out.println("时:"+cal.get(Calendar.HOUR_OF_DAY));
        System.out.println("分:"+cal.get(Calendar.MINUTE));
        System.out.println("分:"+cal.get(Calendar.SECOND));
    }
}

1. Nuestro Calendario para crear una instancia cuando encontramos a través del nombre de la clase .getInstance para crear una instancia , que es un método estático getInstance Calendar, fuimos a ver la fuente puntual

public static Calendar getInstance()
{
    
    
    return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
}

¡Eh! ! ! Descubrí que llamó a un método createCalendar. A diferencia de nuestro método createPizza, pasa la zona horaria y así sucesivamente. Pasamos el sabor, ¡es muy similar! ! 1

2. Haga clic en el método createCalendar.

private static Calendar createCalendar(TimeZone zone,
                                       Locale aLocale)
{
    
    
    CalendarProvider provider =
        LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
                             .getCalendarProvider();
    if (provider != null) {
    
    
        try {
    
    
            return provider.getInstance(zone, aLocale);
        } catch (IllegalArgumentException iae) {
    
    
            // fall back to the default instantiation
        }
    }

    Calendar cal = null;

    if (aLocale.hasExtensions()) {
    
    
        String caltype = aLocale.getUnicodeLocaleType("ca");
        if (caltype != null) {
    
    
            switch (caltype) {
    
    
            case "buddhist":
            cal = new BuddhistCalendar(zone, aLocale);
                break;
            case "japanese":
                cal = new JapaneseImperialCalendar(zone, aLocale);
                break;
            case "gregory":
                cal = new GregorianCalendar(zone, aLocale);
                break;
            }
        }
    }

Solo prestamos atención a los lugares que nos interesan, algunos lugares, no importa si no entiendes

Calendar cal = null; ¡listo para crear una instancia diferente! ! !

Vea cómo creó ** if (aLocale.hasExtensions ()) {** para determinar cuál es el sufijo

case "buddhis t":
cal = new BuddhistCalendar (zone, aLocale);
break; ¿Es para crear diferentes objetos de instancia basados ​​en diferentes sufijos, como nuestro patrón de método de fábrica? !

Supongo que te gusta

Origin blog.csdn.net/qq_22155255/article/details/111734826
Recomendado
Clasificación