当前位置:

首页 > 编程开发 > 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设计模式的工厂模式怎么实现

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Java
    相关文章 更多
    Java单元测试入门:使用JUnit 5编写第一个测试用例
    Java单元测试入门:使用JUnit 5编写第一个测试用例

    面向初学者的JUnit 5实用入门指南。从测试概念、Maven依赖配置,到手把手编写首个单元测试用例及断言验证,助你掌握Java单元测试的核心流程。

    Java变量未初始化报错解析:局部变量与成员变量默认值差异
    Java变量未初始化报错解析:局部变量与成员变量默认值差异

    深入解析Java中局部变量未初始化编译报错与成员变量自动赋予默认值的机制差异,涵盖JVM内存分配、编译期确定性赋值检查与实际排查修复方案。

    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat
    Java获取当前时间并格式化输出:DateTimeFormatter与SimpleDateFormat

    详细讲解在Java中获取当前系统时间并进行格式化输出的两种核心方案:基于Java 8全新日期时间API的DateTimeFormatter与传统遗留的SimpleDateFormat,包含完整代码示例、线程安全机制对比及生产选型建议。

    Java中final与static final常量的定义及初始化规则
    Java中final与static final常量的定义及初始化规则

    深入解析Java中final变量与static final常量的定义、内存语义、初始化时机及合法赋值路径,涵盖编译期常量优化与实战避坑指南。

    Java抽象方法与接口方法的区别及选型建议
    Java抽象方法与接口方法的区别及选型建议

    深入对比Java中抽象类抽象方法与接口方法的语法演进、设计意图及运行期差异,并提供清晰的架构选型决策流程与实战范例。

    Java实现HTTP请求与JSON解析的完整代码示例
    Java实现HTTP请求与JSON解析的完整代码示例

    本文提供Java标准库HttpClient发起HTTP GET/POST请求并结合Jackson进行JSON数据反序列化与序列化的完整代码示例与工程实践指南。

    Java递归出现StackOverflowError的原因分析及栈空间优化方案
    Java递归出现StackOverflowError的原因分析及栈空间优化方案

    详细分析Java递归调用出现StackOverflowError的原因,结合代码说明线程栈、栈帧和递归深度之间的关系,并介绍终止条件排查、迭代改写、减少栈帧开销以及通过-Xss调整JVM栈空间的方法。

    Java空指针异常(NPE)的代码排查与修复实例
    Java空指针异常(NPE)的代码排查与修复实例

    针对Java中常见的NullPointerException(NPE),本文从堆栈日志定位、典型代码触发场景、具体修复代码对比到防御体系进行系统讲解,提供实用且易上手的排查与修复方案。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

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

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

    Windows
    Windows

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

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

    为什么要购买正版软件?
    01 官方授权

    授权来源透明,订单与许可信息可随时查询。

    02 即时交付

    付款成功后自动发放激活信息,支持订单追踪。

    03 中文协助

    安装、激活、迁移与续费问题都有专人响应。

    04 长期可用

    提供升级提醒与授权管理,换机时也能轻松迁移。

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

    Copyright ©2018-2026