Java 深入理解创建型设计模式之抽象工厂模式

 更新时间:2022年02月16日 16:17:34   作者:张起灵-小哥  
当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式,抽象工厂模式是所有形式的工厂模式中最为抽象和最具一般性的一种形态

1.什么是抽象工厂模式?

  • 抽象工厂模式:  定义了一个interface用于创建相关或有依赖关系的对象簇,而无需指明具体的类。
  • 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
  • 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
  • 将工厂抽象成两层,AbsFactory(抽象工厂))和具体实现的工厂子类。程序员可以根据创建对象类型使用对应的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。

我们仍然以上一篇文章的案例为主,画出抽象工厂模式下的类图。

2.案例代码

首先仍然是Pizza种类相关的几个类。

package com.szh.factory.abstractfactory.pizza;
 
/**
 * 声明Pizza类为抽象类
 */
public abstract class Pizza {
    //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;
    }
}
package com.szh.factory.abstractfactory.pizza;
 
public class LDPepperPizza extends Pizza {
 
	@Override
	public void prepare() {
		setName("伦敦的胡椒pizza");
		System.out.println("伦敦的胡椒pizza 准备原材料");
	}
 
}
package com.szh.factory.abstractfactory.pizza;
 
public class LDCheesePizza extends Pizza {
 
	@Override
	public void prepare() {
		setName("伦敦的奶酪pizza");
		System.out.println("伦敦的奶酪pizza 准备原材料");
	}
 
}
package com.szh.factory.abstractfactory.pizza;
 
public class BJPepperPizza extends Pizza {
 
	@Override
	public void prepare() {
		setName("北京的胡椒pizza");
		System.out.println("北京的胡椒pizza 准备原材料");
	}
 
}
package com.szh.factory.abstractfactory.pizza;
 
public class BJCheesePizza extends Pizza {
 
	@Override
	public void prepare() {
		setName("北京的奶酪pizza");
		System.out.println("北京的奶酪pizza 准备原材料");
	}
 
}

下面是抽象工厂和工厂方法的区别之处。

package com.szh.factory.abstractfactory.order;
 
import com.szh.factory.abstractfactory.pizza.Pizza;
 
//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
    //让下面的工厂子类来具体实现
    public Pizza createPizza(String orderType);
}
package com.szh.abstractfactory.order;
 
import com.szh.abstractfactory.pizza.BJCheesePizza;
import com.szh.abstractfactory.pizza.BJPepperPizza;
import com.szh.abstractfactory.pizza.Pizza;
 
public class BJFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if("cheese".equals(orderType)) {
            pizza = new BJCheesePizza();
        } else if ("pepper".equals(orderType)){
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}
package com.szh.abstractfactory.order;
 
import com.szh.abstractfactory.pizza.LDCheesePizza;
import com.szh.abstractfactory.pizza.LDPepperPizza;
import com.szh.abstractfactory.pizza.Pizza;
 
public class LDFactory implements AbsFactory {
    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if ("cheese".equals(orderType)) {
            pizza = new LDCheesePizza();
        } else if ("pepper".equals(orderType)) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}
package com.szh.factory.abstractfactory.order;
 
import com.szh.factory.abstractfactory.pizza.Pizza;
 
import java.util.Scanner;
 
public class OrderPizza {
 
    AbsFactory absFactory;
 
    public OrderPizza(AbsFactory absFactory) {
        setFactory(absFactory);
    }
 
    private void setFactory(AbsFactory absFactory) {
        Pizza pizza = null;
        String orderType = ""; // 用户输入
        this.absFactory = absFactory;
        do {
            orderType = getType();
            // factory 可能是北京的工厂子类,也可能是伦敦的工厂子类
            pizza = absFactory.createPizza(orderType);
            if (pizza != null) { // 订购ok
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println("订购失败");
                break;
            }
        } while (true);
    }
 
    // 写一个方法,可以获取客户希望订购的披萨种类
    private String getType() {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入 pizza 种类: ");
        String str = scanner.nextLine();
        return str;
    }
}

最后是测试类。

package com.szh.abstractfactory;
 
import com.szh.abstractfactory.order.BJFactory;
import com.szh.abstractfactory.order.LDFactory;
import com.szh.abstractfactory.order.OrderPizza;
 
import java.util.Scanner;
 
public class MainTest {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String content = scanner.next();
        if ("Beijing".equals(content)) {
            new OrderPizza(new BJFactory());
        } else if ("London".equals(content)) {
            new OrderPizza(new LDFactory());
        } else {
            System.out.println("无法预先匹配Pizza种类....");
            scanner.close();
        }
    }
}

3.工厂方法 + 抽象工厂总结

  • 工厂模式的意义:将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。
  • 遵循了依赖倒转原则:创建对象实例时,不要直接new类,而是把这个new类的动作放在一个工厂的方法中,并返回。有的书上说,变量不要直接持有具体类的引用。   不要让类继承具体类,而是继承抽象类或者是实现interface(接口)不要覆盖基类中已经实现的方法。

到此这篇关于Java 深入理解创建型设计模式之抽象工厂模式的文章就介绍到这了,更多相关Java 抽象工厂模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Gson序列化指定忽略字段的三种写法详解

    Gson序列化指定忽略字段的三种写法详解

    在我们日常使用json序列化框架过程中,经常会遇到在输出json字符串时,忽略某些字段,那么在Gson框架中,要想实现这种方式,可以怎么处理呢,本文就来介绍一下
    2021-10-10
  • 一篇文章带你了解Java 中序列化与反序列化

    一篇文章带你了解Java 中序列化与反序列化

    这篇文章主要介绍了Java 序列化与反序列化(Serialization),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-07-07
  • spring cloud 使用Eureka 进行服务治理方法

    spring cloud 使用Eureka 进行服务治理方法

    这篇文章主要介绍了spring cloud 使用Eureka 进行服务治理方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Java日常练习题,每天进步一点点(47)

    Java日常练习题,每天进步一点点(47)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-08-08
  • 浅谈Java中向上造型向下造型和接口回调中的问题

    浅谈Java中向上造型向下造型和接口回调中的问题

    这篇文章主要介绍了浅谈Java中向上造型向下造型和接口回调中的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • SpringBoot AOP导致service注入后是null的问题

    SpringBoot AOP导致service注入后是null的问题

    本文主要讲述了如何利用SpringAOP实现用户操作日志的记录,首先,引入SpringBoot的AOP依赖,然后,选择基于注解的形式来实现日志操作,以避免污染原有代码和逻辑,在理解了SpringBootAOP的一些注解后,需要记录用户的正常请求以及异常请求的信息
    2024-10-10
  • SpringData JPA Mongodb查询部分字段问题

    SpringData JPA Mongodb查询部分字段问题

    这篇文章主要介绍了SpringData JPA Mongodb查询部分字段问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Java设计模式之工厂模式(Factory模式)介绍

    Java设计模式之工厂模式(Factory模式)介绍

    这篇文章主要介绍了Java设计模式之工厂模式(Factory模式)介绍,本文讲解了为何使用工厂模式、工厂方法、抽象工厂、Java工厂模式举例等内容,需要的朋友可以参考下
    2015-03-03
  • java编写猜数字游戏

    java编写猜数字游戏

    这篇文章主要为大家详细介绍了java编写猜数字游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • Apache Log4j2 报核弹级漏洞快速修复方法

    Apache Log4j2 报核弹级漏洞快速修复方法

    Apache Log4j2 是一个基于Java的日志记录工具,是 Log4j 的升级,是目前最优秀的 Java日志框架之一,这篇文章主要介绍了突发Apache Log4j2 报核弹级漏洞快速修复方法,需要的朋友可以参考下
    2021-12-12

最新评论