当前位置:

首页 > 编程开发 > Java设计模式的工厂模式怎么实现

Java设计模式的工厂模式怎么实现

工厂模式在Java应用程序中对象无处不在,这些对象都需要进行创建,如果创建的时候直接new对象,那么如果我们要更换对象,所有new对象的地方都需要进行更改。违背了软件设计原则中的开闭原则。如果我们使用工厂生产对象,只需要在工厂中关注对象的改变即可,达到了与对象解耦的目的,工厂模式最大的特点就是解耦合补充:开闭原则:对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。是为了使程序的扩展性好,易于维护和升级。1.简单工厂1.1结构抽象产品:定义了产品的规范,描述了产品

工厂模式

在Java应用程序中对象无处不在,这些对象都需要进行创建,如果创建的时候直接new对象,那么如果我们要更换对象,所有new对象的地方都需要进行更改。违背了软件设计原则中的开闭原则。如果我们使用工厂生产对象,只需要在工厂中关注对象的改变即可,达到了与对象解耦的目的,工厂模式最大的特点就是解耦合

补充:

开闭原则: 对扩展开放,对修改关闭。在程序需要进行扩展的时候,不能去修改原有的代码,实现一个热插拔的效果。是为了使程序的扩展性好,易于维护和升级。

1.简单工厂

1.1结构
  • 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能。

  • 具体产品: 实现或者继承抽象产品的子类

  • 具体工厂: 提供了创建产品的方法,调用者通过该方法来创建产品。

1.2实现

以点咖啡为例:

咖啡抽象类

public abstract class Coffee {
    /**
     * 获取咖啡类型
     * @return
     */
    public abstract  String getName();

    /**
     *加糖
     */
    public  void addSugar(){
        System.out.println("加糖");
    }
    /**
     *加奶
     */
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类

public class AmericanCoffee  extends Coffee{

@Override
    public String getName(){
        return "美式咖啡";
    }
}

拿铁咖啡类

public class LatteCoffee extends Coffee {

    @Override
    public String getName(){
        return "拿铁咖啡";
    }
}

咖啡工厂类

public class CoffeeFactory {

    public Coffee createCoffee(String type){
      Coffee coffee = null;
      if("american".equals(type)){
          coffee = new AmericanCoffee();
      }else if("latten".equals(type)){
          coffee = new LatteCoffee();
      }else{
          throw new RuntimeException("没有此类型的咖啡");
      }
      return coffee;
    }
}

咖啡店类

public class CoffeeStore {

    public Coffee orderCoffee(String type){
        CoffeeFactory factory = new CoffeeFactory();

      //调用生产咖啡的方法
        Coffee coffee = factory.createCoffee(type);
        coffee.addMilk();
        coffee.addSugar();

        return  coffee;
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        CoffeeStore coffeeStore = new CoffeeStore();
        Coffee coffee = coffeeStore.orderCoffee("latten");
        System.out.println(coffee.getName());
    }
}

类图

Java设计模式的工厂模式怎么实现

咖啡工厂负责生产咖啡(具体工厂),咖啡店通过咖啡工厂选取咖啡

其实简单工厂是大家在实际写代码的时候经常用到的,虽然简单工厂实现了咖啡店与咖啡的耦合,但是可以明显看到咖啡与咖啡工厂又耦合起来了,后期如果增加咖啡的新品种,我们需要修改咖啡工厂的代码,这又违背了“开闭原则”。

注意:

简单工厂和不使用工厂是有很大区别的,如果咖啡店有多个,不使用工厂如果遇到新增咖啡需要修改所有咖啡店,但是使用工厂只需要修改咖啡工厂,类似于将所有咖啡店抽取出一个抽象的咖啡店。

1.3优缺点

优点:

封装了创建对象的过程,可以通过参数直接获取对象,把对象的创建和业务逻辑层分开,这样可以避免之后修改客户代码,如果需要实现新产品直接修改工厂类,更容易扩展。

缺点:

增加新产品时还需要修改工厂类的代码,违背了“开闭原则”。

1.4扩展

静态工厂,将工厂类中创建对象的功能定义为静态的,这样不需要再创建工厂类,直接通过类名调用静态方法,类似于工具类

public class CoffeeFactory {
  //静态方法
    public static Coffee createCoffee(String type){
      Coffee coffee = null;
      if("american".equals(type)){
          coffee = new AmericanCoffee();
      }else if("latten".equals(type)){
          coffee = new LatteCoffee();
      }else{
          throw new RuntimeException("没有此类型的咖啡");
      }
      return coffee;
    }
}

2.工厂方法

对工厂进行抽象,每一种产品对应一个具体工厂,新增产品只需要再新增对应的具体工厂,符合”开闭原则“

2.1结构
  • 抽象工厂: 提供创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品

  • 具体工厂: 主要是实现抽象工厂中的抽象方法,完成具体产品的创建

  • 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能

  • 具体产品: 实现抽象产品所定义的接口,由具体工厂来创建,与具体工厂之间一一对应

2.2实现

抽象咖啡类和具体咖啡类不变

咖啡工厂(抽象工厂)

public interface CoffeeFactory {
    /**
     * 创建咖啡
     * @return
     */
    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();
    }
}

咖啡店

public class CoffeeStore {

    private CoffeeFactory factory;

    public void setFactory(CoffeeFactory factory) {
        this.factory = factory;
    }

    /**
     * 点咖啡
     */
    public Coffee orderCoffee() {
        Coffee coffee = factory.createCoffee();
        coffee.addSugar();
        coffee.addMilk();
        return coffee;
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        //创建咖啡店对象
        CoffeeStore coffeeStore = new CoffeeStore();
        //创建工厂对象
        CoffeeFactory factory = new AmericanCoffeeFactory();
        coffeeStore.setFactory(factory);

        //点咖啡
        Coffee coffee = coffeeStore.orderCoffee();

        System.out.println(coffee.getName());
    }
}

类图

Java设计模式的工厂模式怎么实现

我们只需要知道所点咖啡具体对应的工厂对象,通过咖啡店调用对应的工厂,由工厂创建咖啡对象实现点咖啡的过程

2.3优缺点

优点:

  • 用户只需要知道具体工厂就可以获得所需产品,无需知道产品的具体创建过程

  • 在系统新增产品时只需要添加具体产品类和对应的具体工厂类,无需对原工厂进行修改符合“开闭原则”

缺点:

每增加一个产品就要增加一个对应的具体工厂类,增加的系统的复杂性。如果具体产品种类过多,那么大量的工厂类不仅难以管理,而且也会造成程序中创建的对象过多,严重影响内存性能

3.抽象工厂

3.1结构
  • 抽象工厂: 提供创建产品的接口,包含多个创建产品的方法,可以创建多个不同等级的产品

  • 具体工厂: 主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建

  • 抽象产品: 定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品

  • 具体产品: 实现抽象产品所定义的接口,由具体工厂来创建,与具体工厂是多对一关系

3.2实现

咖啡抽象类

public abstract class Coffee {
    /**
     * 获取咖啡类型
     * @return
     */
    public abstract  String getName();

    /**
     *加糖
     */
    public  void addSugar(){
        System.out.println("加糖");
    }
    /**
     *加奶
     */
    public void addMilk(){
        System.out.println("加奶");
    }
}

美式咖啡类

public class AmericanCoffee  extends Coffee{

@Override
    public String getName(){
        return "美式咖啡";
    }
}

拿铁咖啡类

public class LatteCoffee extends Coffee {

    @Override
    public String getName(){
        return "拿铁咖啡";
    }
}

甜品抽象类

public abstract class Dessert {
 //甜品抽象类

    public abstract void show();
}

抹茶慕斯类

public class MatchaMousse extends Dessert{

//抹茶慕斯类
    @Override
    public void show() {
        System.out.println("抹茶慕斯");
    }


}

提拉米苏类

public class Tiramisu  extends Dessert{
 //提拉米苏类
    @Override
    public void show() {
        System.out.println("提拉米苏");
    }
}

甜品工厂

public  interface DessertFactory {

    /**
     * 生产咖啡
     * @return
     */
    Coffee createCoffee();

    /**
     * 生产甜品
     * @return
     */
    Dessert createDessert();

}

美式风味甜品工厂类

public class AmericanDessertFactory  implements DessertFactory{
    /**
     *美式风味甜品工厂
     * 可以生产美式咖啡和抹茶慕斯
     */
    @Override
    public Coffee createCoffee() {
        return new AmericanCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new MatchaMousse();
    }
}

意大利风味甜品工厂类

public class ItalyDessertFactory implements DessertFactory {

    /**
     *意大利风味甜品工厂
     * 可以生产拿铁咖啡和提拉米苏
     */
    @Override
    public Coffee createCoffee() {
        return new LatteCoffee();
    }

    @Override
    public Dessert createDessert() {
        return new Tiramisu();
    }
}

测试类

public class Test {
    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();

    }
}

类图

Java设计模式的工厂模式怎么实现

由类图可见,抽象工厂不再是一个具体工厂对应一个产品,而是一个具体工厂对应一个产品族。如果需要增加一个产品族只需加对应的工厂类,符合”开闭原则“

3.3优缺点

优点:

在工厂方法的基础上减少了部分对象的创建,适合于每次只使用同一产品族的对象这类应用场景

缺点:

当产品族中需要增加一个产品时,所有工厂都要修改

4.模式扩展

配置文件+简单工厂

通过工厂模式+配置文件的方式解除工厂对象和产品对象的耦合。在工厂类中加载配置文件的全类名,通过反射创建对象并存储在容器中,如果需要直接从容器中获取(Spring IOC原理)

4.1实现

1.定义配置文件

american = com.xue.config_factory.AmericanCoffee
latten = com.xue.config_factory.LatteCoffee

2.改进工厂类

public class CoffeeFactory {

    /**
     * 加载配置文件,获取配置文件中配置的全类名,并创建该类的对象进行存储
     */

    //1.定义容器对象存储咖啡对象
    private static HashMap map = new HashMap<>();


    //2.加载配置文件
    static {
        //创建 Properties对象
        Properties properties = new Properties();
        //调用properties对象中的load方法进行配置文件的加载
        InputStream is = CoffeeFactory.class.getClassLoader().getResourceAsStream("bean.properties");
        try {
            properties.load(is);
            //从properties中获取全类名
            Set keys = properties.keySet();

            for (Object key : keys) {
                String className = properties.getProperty((String) key);
                //通过反射创建对象
                Class class1 = Class.forName(className);
                Coffee coffee = (Coffee) class1.newInstance();

                //将名称和对象存储在容器中
                map.put((String) key,coffee);

            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //根据名称获取对象
    public static Coffee createCoffee(String name) {


        return map.get(name);
    }
}

静态成员变量用来存储创建的对象(键存储的是名称,值存储的是对应的对象),而读取配置文件和创建对象写在静态代码块中只需要执行一次

测试类

public class Test {
    public static void main(String[] args) {
        Coffee coffee = CoffeeFactory.createCoffee("american");
        System.out.println(coffee.getName());

        System.out.println("------------");

        Coffee latten = CoffeeFactory.createCoffee("latten");
        System.out.println(latten.getName());

    }

}

成功!!!

Java设计模式的工厂模式怎么实现

本文内容来源于互联网,如有侵权请联系删除。
作者最新文章
编程开发
相关文章 更多
谷歌浏览器Mac版入口
谷歌浏览器Mac版入口

谷歌浏览器Mac版官方安装指南 谷歌浏览器Mac版官方安装入口是https://www.google.com/chrome/,需macOS 12+系统、500MB空间,下载.dmg后拖入应用程序安装,支持多设备同步、性能优化与隐私保护功能。 苹果电脑Chrome的安装入口究竟在哪里?这个问题最近可是

Chrome浏览器JS脚本不运行怎么办
Chrome浏览器JS脚本不运行怎么办

Chrome中JavaScript未执行需依次检查:一、移除站点级禁用并添加允许域名;二、开启全局JavaScript开关;三、禁用干扰扩展;四、在开发者工具中启用JavaScript;五、重置内容设置为默认。 有时在Chrome里打开网页,会发现交互按钮点了没反应,数据加载不出来,页面仿佛“静止”

IE浏览器怀旧版在线网址
IE浏览器怀旧版在线网址

IE浏览器怀旧版在线网址:一次精准的技术时光回溯 最近,不少老用户和怀旧爱好者在反复搜索一个问题:那个经典的Internet Explorer,如今还能在哪里原汁原味地体验到?答案指向一个特定的地址:https://ie.microsoft.com/legacy/。 这个网站远不止是一个简单的“皮肤

火狐浏览器有哪些设置功能
火狐浏览器有哪些设置功能

火狐浏览器五大核心设置功能:解锁高效、安全与个性化体验 火狐浏览器功能强大,但如果不仔细挖掘,很多能大幅提升效率和安全性的设置可能就“藏着掖着”了。这就好比拥有一台高性能设备,却只用了基础模式。那么,如何把它调整到最顺手、最安全的状态?接下来,我们就聚焦于当前版本(截至2025年末)最关键的五大设置

chrome搜索免验证入口
chrome搜索免验证入口

Chrome官方免验证入口为https://www.google.cn/chrome/,提供全平台安装包、免登录即用、本地化安全机制及引擎级性能优化。 到底该去哪里找正版、免费且无需繁琐验证的Chrome浏览器入口?这个问题困扰了不少网友。今天,我们就来直通核心,为大家详细拆解Chrome引擎的官方

java heap space 选型思路:使用场景与区别整理
java heap space 选型思路:使用场景与区别整理

Java堆是JVM存储对象的核心内存区域,配置需结合场景:单体应用适中设置;大数据处理需大堆并关注GC停顿;微服务强调快速启动;高并发需精细划分堆区域。关键参数-Xms和-Xmx建议等值以稳定性能。垃圾回收器选择影响效率,如G1适用于大堆,ZGC可实现低停顿。内存错误时需监控堆状态。

java heap space 使用中遇到的问题怎么解决
java heap space 使用中遇到的问题怎么解决

Java堆内存溢出错误通常因内存泄漏、数据处理需求过大或JVM参数配置不当引起。排查时可借助jmap、堆转储及MAT等工具定位问题。解决方案包括调整JVM内存参数(如-Xmx)、修复代码中的内存泄漏、优化大数据处理逻辑,并建立持续监控与预防机制,以保障应用稳定运行。

java xml 选型思路:使用场景与区别整理
java xml 选型思路:使用场景与区别整理

XML在Java开发中用于配置、数据交换等场景。解析方式主要有DOM、SAX、StAX及第三方库。DOM适合操作小文件,SAX/StAX适合处理大文件流,JAXB用于对象与XML映射。选型需结合数据大小、内存、性能及团队熟悉度,现代框架常封装底层解析。

using namespace 使用中遇到的问题怎么解决
using namespace 使用中遇到的问题怎么解决

命名空间的基本概念与常见引入问题在C++等编程语言中,命名空间(namespace)是一种将代码标识符(如变量、函数、类名)封装在特定名称下的机制,其主要目的是避免命名冲突,尤其是在大型项目或使用多个第三方库时。使用“using namespace”指令可以将指定命名空间中的所有名称引入当前作用域,

c语言函数递归 实操经验总结:这些技巧很实用
c语言函数递归 实操经验总结:这些技巧很实用

理解递归的基本原理在C语言中,递归是一种函数调用自身的编程技术。要掌握它,首先需要理解其核心思想:将一个复杂的大问题,分解为一个或几个与原问题相似但规模更小的子问题,直到子问题足够简单,可以直接求解。这个过程通常包含两个关键部分:递归出口和递归体。递归出口定义了问题何时不再继续分解,即最简单、可直接

查看更多
精品专题 更多
装机必备
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows
Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

macOS软件
macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

Mac软件 更多
灵活计算器
灵活计算器
macOS/iOS/Android

灵活计算器是一款笔记式算数应用,支持实时计算、动态关联和云端同步功能。记录、整理和输出之间的过渡会更自然,适合长期写作、做笔记或持续沉淀个人内容。

赤友清理大师
赤友清理大师
macOS

赤友清理大师是一款为 Mac 设计的智能清理优化工具,可精准扫描垃圾、大文件、重复文件等,释放磁盘空间。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

WINDOWS 更多
Windows 10
Windows 10
Windows

Windows 10 是一款微软推出的经典操作系统,拥有硬件兼容性与多任务处理能力。它更偏向把系统状态查看和常用调节动作放在一起,适合需要持续观察和微调设备状态的场景。

极度公式
极度公式
Windows/macOS/Linux

极度公式是一款跨平台专业LaTeX公式识别编辑软件,支持OCR公式识别和多平台编辑。和使用说明,避免使用,享受完整功能与稳定支持。做扫描整理、文字提取和表格转换时,它能把识别后的处理步骤接得更顺,资料录入这类场景会省下不少时间。

密码键盘
密码键盘
Windows/macOS/iOS/Android

密码键盘是一款兼具安全性与便捷性的高效密码管理器。日常使用里的持续防护和信息管理会更突出,适合把安全控制放进长期使用流程中的场景。

网站备案号:苏ICP备2026018738号-1 联系邮箱:bd@zhengruan.com 网站地图

Copyright ©2018-2026