2.Java设计模式-----抽象工厂模式(Abstract Factory Pattern)

2023-11-16

抽象工厂模式(Abstract Factory),是23种设计模式之一。抽象工厂模式是这样子定义的:

抽象工厂模式,提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。

       在学习抽象工厂模式之前,最好熟悉简单工厂模式以及工厂方法模式,这样对理解抽象工厂模式会有一定帮助,而且抽象工厂模式是基于工厂方法模式而来的。如果你还没有了解到什么是简单工厂模式以及工厂方法模式,你可以去了解一下:1.大白话讲解-----工厂方法模式(Factory Pattern)     工厂模式------关心的是结果

       你可能看着上面的定义,一时无法理解它到底是什么意思。 你可以接着继续往下面看,看了这个实例,我相信你应该就能够理解上面这句话的含义了。

现在我们有一个新的需求:

        ①现在我有一套系统,系统里面分别用到了MySQL和Oracle数据库。

        ②我需要对这两套数据库进行相同的操作,比如:我要对MySQL和Oracle进行用户信息的相同操作(insert,get用户信息等)

现在既然已经有了相关的需求,那我们现在就可以来对该需求进行一些简单的分析:

        ①数据库两套:MySQL、Oracle

        ②分别要对两套数据库中的数据,都进行insert操作、get信息操作

接下来,我们就来按照我们平常的思路,来编写一下代码了。

①我们现在分别有两个类MySQLUser类、OracleUser类,然后类里都有insertUser()和getUser()方法来实现相关操作

//1.MySQLUser.java
public class MySQLUser {
    public void insertUser(){
        System.out.println("我是MySQL中的insert方法");
    }
    public void getUser(){
        System.out.println("我是MySQL中的getUser方法");
    }
}
//2.OracleUser.java
public class OracleUser {
    public void insertUser(){
        System.out.println("我是Oracle中的insertUser方法");
    }
    public void getUser(){
        System.out.println("我是Oracle中的getUser方法");
    }
}

然后我们在main方法中测试一下:

public class Test {
    public static void main(String[] args) {
        MySQLUser mysql = new MySQLUser();
        mysql.getUser();//打印结果:我是MySQL中的getUser方法
        mysql.insertUser();//打印结果:我是MySQL中的insert方法
        OracleUser oracle = new OracleUser();
        oracle.getUser();//打印结果:我是Oracle中的getUser方法
        oracle.insertUser();//打印结果:我是Oracle中的insertUser方法
    }
}

如上结果,完全可以实现我们的功能。但是,看上去确实有点太low了。如果我有10个乃至100个地方需要用到mysql对象,那么我每次都需要new MySQLUser()才能够获取到一个mysql对象,然后对其进行操作。借用工厂方法模式,我们可以来一个工厂方法Factory来帮助我们去创建mysql对象和oracle对象。

②接下来,我们可以将其进一步进行修改。

       1.从MySQLUser类和OracleUser类中抽取出一个IUser接口,接口包括insertUser()和getUser()抽象方法

       2.MySQLUser类和OracleUser类,分别实现IUser接口,然后重写insertUser()和getUser()方法

       3.创建MySQLFactory和OracleFactory工厂类,主要用来创建用户,从工厂类中可以抽取出一个IFactory接口,接口包括createUser()抽象方法

       4.MySQLFactory类和OracleFactory类,分别实现IFactory接口,并且重写createUser()方法

       5.进行测试

代码实现具体如下:

//1.IUser接口
public interface IUser {
    public void insertUser();
    public void getUser();
}
//2.1 MySQLUser类实现IUser
public class MySQLUser implements IUser {
    @Override
    public void insertUser(){
        System.out.println("我是MySQL中的insert方法");
    }
    @Override
    public void getUser(){
        System.out.println("我是MySQL中的getUser方法");
    }
}
//2.2 OracleUser类实现IUser
public class OracleUser implements IUser {
    @Override
    public void insertUser(){
        System.out.println("我是Oracle中的insertUser方法");
    }
    @Override
    public void getUser(){
        System.out.println("我是Oracle中的getUser方法");
    }
}
//3.IFactory接口
public interface IFactory {
    public IUser createUser();
}
//4.1 MySQLFactory类实现IFactory 
public class MySQLFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new MySQLUser();
    }
}
//4.2 OracleFactory类实现IFactory 
public class OracleFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new OracleUser();
    }
}
//5.测试
public class Test01 {
    public static void main(String[] args) {
        IFactory factory = new MySQLFactory();
        IUser user = factory.createUser();
        user.insertUser(); //打印结果:我是MySQL中的insert方法
        user.getUser();//打印结果:我是MySQL中的getUser方法
    }
}

       如果现在我不用MySQL了,目前要换成Oracle,则只需要将new MySQLFactory()换成new OracleFactory()即可。你会发现这完全就是工厂方法模式。对的。就是工厂方法模式的实现。我们开头就说到:抽象工厂模式是基于工厂方法模式而来的。接下来,我们再继续向着抽象工厂模式继续演进吧

③现在我们又有了新的需求:

          现在MySQL和Oracle中,都有一张日志Log表,我们在insertUser之后,都要向日志表中添加一条数据

    现在我们来对这个需求进行一下简单的分析:

          1.之前MySQLUser和OracleUser分别有一个insertUser()和getUser()方法,目前它们都需要往日志表中添加日志

          2.所以我们现在抽取出一个ILog接口,接口中有一个insertLog()抽象方法

          3.新建一个MySQLLog类和OracleLog类,分别实现ILog接口,然后重写insertLogr()方法

          4.之前IFactory接口已有createUser()功能的情况下,在该接口中新增一个createLog()抽象方法,来满足插入日志的功能

          5.MySQLFactory类和OracleFactory类,因为实现了IFactory接口,需要重写createLog()方法

          6.开启测试

//2.ILog接口
public interface ILog {
    public void insertLog();
}
//3.1 MySQLLog实现ILog接口
public class MySQLLog implements ILog {
    @Override
    public void insertLog() {
        System.out.println("我是MySQL中的insertLog方法");
    }
}
//3.2 OracleLog实现ILog接口
public class OracleLog implements ILog {
    @Override
    public void insertLog() {
        System.out.println("我是Oracle中的insertLog方法");
    }
}
//4.IFactory接口新增createLog()方法
public interface IFactory {
    public IUser createUser();
    public ILog createLog();
}
//5.1 MySQLFactory工厂类重写新增的createLog()方法
public class MySQLFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new MySQLUser();
    }
    @Override
    public ILog createLog() {
        return new MySQLLog();
    }
}
//5.2 OracleFactory工厂类重写新增的createLog()方法
public class OracleFactory implements IFactory {
    @Override
    public IUser createUser() {
        return new OracleUser();
    }
    @Override
    public ILog createLog() {
        return new OracleLog();
    }
}
//6.开启测试
public class Test02 {
    public static void main(String[] args) {
        IFactory factory = new MySQLFactory();
        IUser mysql = factory.createUser();
        mysql.getUser(); //打印结果:我是MySQL中的getUser方法

        ILog log = factory.createLog();
        log.insertLog(); //打印结果:我是MySQL中的insertLog方法
    }
}

④我们现在有个改变,就是说在③中第6步测试中,我们现在业务要废弃MySQL而使用Oracle了,现在我们只需要将第6步中的new MySQLFactory() 换成 new OracleFactory()即可。而无需改动其他代码,就能够解决业务的变动,这就已经明显解决了与具体数据库之间的耦合关系

⑤如果我们现在又要换成SqlServer呢。则我们现在只需要实现如下几步,即可满足要求

         1.创建一个SqlServerUser,来实现已写好的IUser接口,并重写其中的insertUser()和getUser()方法。

         2.创建一个SqlServerFactory,实现已写好的IFactory接口,并重写其中的createUser()方法。

         3.在③中第6步测试中,直接将new MySQLFactory()换成new SqlServerFactory()即可。

         4.这样就可以最大程度上解决功能与业务代码之间的耦合,将修改工作量降到最低。

⑥实际上我们这次代码的重构中,已经使用到了抽象工厂模式,抽象工厂可能表面上看起来貌似与工厂方法模式没什么区别的。所以,抽象工厂模式是基于工厂方法模式而来的。现在你在重头来看一下抽象工厂模式的定义:抽象工厂模式,提供一个创建一系列相关或互相依赖对象的接口,而无需指定它们具体的类。你也许可能就会有所体会

⑦在该实例中,你完全可以理解成是多个工厂方法的组合。

⑧抽象工厂模式的优点:

        1.方便交换产品系列,诸如在本实例中,如果现在业务需求需要将MySQL替换为Oracle或者SqlServer,你只需要将new MySQLFactory()替换为new OracleFactory()或者new SqlServerFactory()即可满足要求。这样可以在保证在最小改动的情况下而完成对整体业务的修改,起到了最大程度的解耦操作。

        2.在实现过程(xxxFactory类中)和具体使用中(测试类中),我们通过向上造型用到IFactory,IUser,ILog类,我们在具体使用中就用到了上面三个类,我们通过factory.createUser()来创建用户,通过factory.createLog()来插入日志。如果没有new xxxFactory()的话,我们完全不知道我们是在操作哪个类型的数据库,从而达到了实现类和使用之间的隔离。

⑨抽象工厂模式的缺点:

         在我们每次需要createUser和createLog的时候,我们都需要通过IFactory factory = new xxxFactory();来获取到factory对象,然后对其进行相关的操作。如果我现在有100个地方需要使用,则需要来100次new操作,这显然是太扯淡了。这算的上一个缺点吧。

⑩面对⑨中的缺点,我们该如何解决这种问题?

       我们可以使用反射机制来解决,可以参考1.大白话讲解-----工厂方法模式(Factory Pattern)中的⑩部分来做出修改,这就是抽象工厂方法了。

附:全文实例结构图:

Demo实例地址: https://download.csdn.net/download/lzb348110175/11147854

---->如有疑问,请发表评论,或者联系博主:lzb348110175@163.com,欢迎哦^_^

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

2.Java设计模式-----抽象工厂模式(Abstract Factory Pattern) 的相关文章

  • Java复习-25-单例设计模式

    单例设计模式 目的 使用场景 在实际开发下 会存在一种情况 某一种类在程序的整个生命周期中 只需要实例化一次就足够了 例如 系统数据类 由于操作系统只有一个 因此在程序初始化时该类只需要实例化一次 之后的系统数据更改都是在这一个实例化对象中
  • 离散仿真引擎基础作业与练习

    作业内容 一 简答题 1 解释 GameObjects 和 Assets 的区别与联系 2 下载几个游戏案例 分别总结资源 对象组织的结构 3 使用 debug 验证 MonoBehaviour 基本行为或事件触发条件 4 了解 GameO
  • 计算资源合并模式——云计算架构常用设计模式

    背景 云计算的解决方案中 最初设计可能有意遵循关注点分离的设计原则 把操作分解为独立的计算单元以便可以单独托管和部署 然而 虽然这种策略可以帮助简化解决方案的逻辑实现 但是在同一个应用程序中要部署大量的计算单元 这会增加运行时的托管成本 并
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • C++设计模式-State状态模式

    State状态模式作用 当一个对象的内在状态改变时允许改变其行为 这个对象看起来像是改变了其类 UML图如下 State类 抽象状态类 定义一个接口以封装与Context的一个特定状态相关的行为 ConcreteState类 具体状态 每一
  • 设计模式——简单工厂模式

    简单工厂模式定义为 简单工厂模式又称为静态工厂方法模型 它属于类创建型模式 在简单工厂模式中 可以根据参数的不同返回不同类的实例 简单工厂专门定义一个类来负责创建其他类的实例 被创建的实例通常都具有共同的父类 简单工厂模式结构图 简单工厂模
  • 设计模式一之简单工厂模式

    生活示例 刻板印刷 gt 活字印刷举例 喝酒唱歌 人生真爽 gt 对酒当歌 人生几何 可维护 需要修改 则只需要改需要改的字即可 可复用 字体可在后来的印刷复用 可扩展 需要加字 只需要加入相应的刻字即可 灵活性好 字的排列可能竖排或横排
  • Java 多线程模式 —— Guarded Suspension 模式

    Part1Guarded Suspension 模式的介绍 我们只从字面上看 Guarded Suspension 是受保护暂停的意思 1Guarded Suspension 模式 在实际的并发编程中 Guarded Suspension
  • Java并发编程之设计模式

    同步模式之保护性暂停 1 定义 即 Guarded Suspension 用在一个线程等待另一个线程的执行结果 要点 有一个结果需要从一个线程传递到另一个线程 让他们关联同一个 GuardedObject 如果有结果不断从一个线程到另一个线
  • 第12课:生活中的构建模式——想要车还是庄园

    用程序来模拟生活 从剧情中思考构建模式 与工厂模式的区别 与组合模式的区别 构建模式的模型抽象 类图 基于升级版的实现 模型说明 应用场景 故事剧情 下周就要过年了 这是 Tony 工作后的第一个春节 还是在离家这么远的北京工作 所以肯定不
  • 单例模式的八种写法比较

    单例模式是最常用到的设计模式之一 熟悉设计模式的朋友对单例模式都不会陌生 一般介绍单例模式的书籍都会提到 饿汉式 和 懒汉式 这两种实现方式 但是除了这两种方式 本文还会介绍其他几种实现单例的方式 让我们来一起看看吧 简介 单例模式是一种常
  • Tomcat 系统架构与设计模式之工作原理篇

    本文以 Tomcat 5 为基础 也兼顾最新的 Tomcat 6 和 Tomcat 4 Tomcat 的基本设计思路和架构是具有一定连续性的 Tomcat 总体结构 Tomcat 的结构很复杂 但是 Tomcat 也非常的模块化 找到了 T
  • Java设计模式之装饰者设计模式Decorator Pattern

    目录 一 基本概念 二 结构 1 图示 三 案例演示 被装饰对象的基类 一个接口 有cost 和description 两个抽象方法 具体被装饰的对象 实现上面这个接口 装饰者抽象类 基类 实现drink接口 具体的装饰者类 糖 具体装饰者
  • 设计模式——State(状态)模式

    目录 前言 1 定义 2 适用性 3 结构 3 1 结构图 3 2 参与者 4 应用举例 4 1 State TcpState 4 2 Context TcpConnection 4 3 ConcreteState ListeningTcp
  • DDD专家张逸:构建领域驱动设计知识体系

    张逸 读完需要 5分钟 速读仅需 2 分钟 领域驱动设计专家 曾就职于 ThoughtWorks 作为 Lead Consultant 为客户提供架构设计 大数据分析 持续交付 代码质量 敏捷管理等咨询服务 著译作包括 软件设计精要与模式
  • 设计模式详解---策略模式

    1 策略模式简介 策略模式 Strategy Pattern 是一种行为型设计模式 用于在运行时根据不同的情境选择不同的算法或策略 该模式将算法封装成独立的类 使得它们可以相互替换 而且可以独立于客户端使用它们的方式 1 1 主要角色 上下
  • 设计模式—迭代器模式解析

    本文参考学习了 图解设计模式 中的代码实现和原理解释 迭代器模式 简介 Iterator 模式用于在数据集合中按照顺序遍历集合 就类似于我们的循环 一个个去遍历一个集合中的所有元素 示例代码 首先我们思考一个书本和书架的关系 显然 书架可以
  • 设计模式(三)-结构型模式(4)-组合模式

    一 为何需要组合模式 Composite 在代码设计中 有种情况是对象之间存在层次关系 即对象之间会存在父结点和子结点的关系 比如在文件管理系统中 所有文件和文件夹形成树状结构 文件夹目录里存在子文件夹和文件 文件夹属于枝结点 文件属于叶结
  • 【设计模式之美】面向对象分析方法论与实现(二):需求到接口实现的方法论

    文章目录 一 进行面向对象设计 1 划分职责 gt 需要有哪些类 2 定义类及其属性和方法 3 定义类与类之间的交互关系 4 将类组装起来并提供执行入口 二 如何进行面向对象编程 1 接口实现
  • 【设计模式之美】 SOLID 原则之五:依赖反转原则:将代码执行流程交给框架

    文章目录 一 控制反转 IOC 二 依赖注入 DI 三 依赖注入框架 DI Framework 四 依赖反转原则 DIP 一 控制反转 IOC 通过一个例子来看一下 什么是控制反转 public class UserServiceTest

随机推荐

  • 使用Hexo 配置自己的博客

    安装前提 在Windows下可以到git官网 推荐使用代理 或者对应的镜像网站进行下载 安装git客户端 安装node js 使用git bash 安装 cURL curl https raw github com creationix n
  • Zotero:按GB/T7714 2015引用参考文献

    欢迎关注 ManTou馒头公众号 原创不易 转载请注明出处 点赞收藏再走 主要解决引用英文文献作者超过3个时出现 等 而不是 etal 的问题 Zotero 按GB T7714 2015引用参考文献 导入China National Sta
  • 剖析vue常见问题(一)之v-for与v-if的优先级

    背景 vue中经常使用到v for和v if 那么它们的优先级是怎么样的呢 怎么才能实现性能优化呢 下面来简单分析一下 如何分析 请参考以下测试demo 以及源码中参考src compiler codegen index js demo代码
  • 棋盘覆盖问题-递归分治

    输入 3 3 4 输出 如图 x 3 y 3代表特殊方块的坐标 坐标原点在坐标系左上角 如图也就是一个 size 4 的L型骨牌的棋盘覆盖问题 include
  • maven集成cucumber,mvn test单元测试不运行

    maven集成cucumber mvn test单元测试不运行 项目已集成cucumber jacoco测试覆盖率100 在application项目添加单元测试 覆盖率下降 发现单元测试覆盖的语句覆盖率没有统计到 经试验 发现是appli
  • Java Web工程中的web.xml配置文件

    Java Web工程中的web xml配置文件 前言 1 xml文件 xml文件 Extentsible Markup Language即可扩展标记语言 是用来定义其它语言的一种元语言 其前身是SGML 标准通用标记语言 xml文件是互联网
  • vue axios 跨域,携带cookie

    前端设置 axios 跨域 const axios require axios axios defaults withCredentials true 后端设置 express app use function req res next r
  • 宏函数、普通函数、内联函数的区别

    示例代码 宏函数 define SUM x x x 内联函数 inline int sum int x return x x 普通函数 int sum int x return x x 什么是内联函数 在普通函数定义时加上 inline 关
  • TCP/IP 协议——知识集锦

    精通 TCP IP 熟练使用 Socket 进行网路编程 这句话在招聘要求里经常见 但是平时压根用不到 虽然笔者用Unity3D 如果做联网需要用到Socket通信 奈何我还没做过网络游戏 这里补下相关知识 目录 1 什么是 TCP IP
  • Java——3.字符串的替换和去除空格操作_replace ()和 trim ()方法

    程序开发中 用户输入数据时经常会有一些错误和空格 这时可以使用 String 类的 replace 和 trim 方法 进行字符串的替换和去除空格操作 ExampleAPI04 public class ExampleAPI04 publi
  • tf卡低级格式化_tf卡写保护怎么去掉 磁盘被写保护解决方法

    今天智智教大家如何去除TF卡写的保护 MicroSD 卡是一种极细小的快闪存储器卡 原本这种记忆卡称为T Flash 有时候我们会遇到tf卡写保护的情况 要解除写保护 先确认一下是否真的被写保护 鼠标右键点击移动硬盘 属性 看看你的文件属性
  • R语言中使用dplyr包进行排序与添加序号的实战

    R语言中使用dplyr包进行排序与添加序号的实战 在R语言中 dplyr是一个非常强大的数据处理包 它提供了一套简洁而一致的函数 用于对数据进行筛选 排序 汇总和变形等操作 本文将介绍如何使用dplyr包进行排序 并为数据添加序号 首先 让
  • java的反射机制Class.forName()

    Class forName 方法的作用 就是初始化给定的类 1 Class 类概念 Class 也是一个 Java 类 保存的是与之对应 Java 类的 meta信息 元信息 用来描述这个类的结构 比如描述一个类有哪些成员 有哪些方法等 一
  • 【网易严选】iOS持续集成打包(Jenkins+fastlane+nginx)

    本文来自网易云社区 作者 孙娇 严选iOS客户端的现有打包方式是通过远程连接打包机执行脚本去打包 打完包会输出相应的ipa的二维码 扫一扫二维码可以安装 但是随着测试队伍的壮大 外包同学越来越多 在打包机输入命令的方式可用度越来越低 手动输
  • 170_web服务器_两个需求【1-】获取虚拟机上数据库数据显示到网页 【2-】网页下拉框数据,发送到MQTT服务器上【html实现网页,.js实现内在,.cgi实现内核】

    实例 html 两个功能一起实现在网页 表面
  • 三种方法带你新建一个SpringBoot项目

    SpringBoot 的设计目的是简化Spring的搭建与开发 尤其是没有了好多繁琐的配置 本篇文章主要介绍如何搭建SpringBoot项目 从官网创建 访问Spring的官方网站 https start spring io 如下 只需要简
  • 小学生创客教学

    在这个互联网 的时代 我们的孩子接受到的信息越来越多 创课要彻底改变传统课程存在的过分传授 形式固化 单调无趣的现状 给学生更多自由探索的空间 激发孩子内在的创造潜能 格物斯坦认为 学生不再是被动的学习者 而是可以像科学家一样以研究的方式去
  • 经典面试题 TCP和UDP有什么区别?

    经典面试题 TCP和UDP有什么区别 解决面试题 斩获心仪的 Offer 文章目录 经典面试题 TCP和UDP有什么区别 一 TCP和UDP是什么 二 TCP和UDP有什么区别 1 TCP和UDP区别总结 2 TCP三次握手和四次挥手 2
  • 数据库的用户信息表设计

    用户信息表在很多情况下都需要有 属于一个项目开篇的基础 这个不搞好以后就会给自己带来麻烦 我参考该博文设计 浅谈数据库用户表结构设计 只是有些地方我实践之后需要补充一下 user表字段 user auth表 要补充说明的是 nickname
  • 2.Java设计模式-----抽象工厂模式(Abstract Factory Pattern)

    抽象工厂模式 Abstract Factory 是23种设计模式之一 抽象工厂模式是这样子定义的 抽象工厂模式 提供一个创建一系列相关或互相依赖对象的接口 而无需指定它们具体的类 在学习抽象工厂模式之前 最好熟悉简单工厂模式以及工厂方法模式