【从零开始学设计模式】第四章_抽象工厂模式(与工厂方法模式区分)

第四章_抽象工厂模式(与工厂模式区分)

1.介绍

1.1定义

为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类 就能得到同族的不同等级的产品的模式结构;

1.2解决的问题

主要解决接口选择的问题。

1.3应用实例

  • 系统中有多个产品族, 每个具体工厂创建同族但属于不同等级的产品;
  • 系统一次只可能消费其中某一族产品,即同族的产品一起使用。

1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。

1.5角色

  • 抽象产品(Abstract Product):定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法。

  • 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。

  • 抽象工厂(Abstract Factory):声明了一组用于创建产品对象的方法,每个方法对应一种产品类型。抽象工厂可以是接口或抽象类。

  • 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品对象的实例。

2.举例

创建 Shape 接口和实现这些接口的实体类。下一步是创建抽象工厂类 AbstractFactory。接着定义工厂类 ShapeFactoryColorFactory,这两个工厂类都是实现了 AbstractFactory。然后创建一个工厂创造器/生成器类 FactoryProducer

AbstractFactoryPatternDemo 类使用 FactoryProducer 来获取 AbstractFactory 对象。它将向 AbstractFactory 传递形状信息 ShapeCIRCLE / RECTANGLE / SQUARE),以便获取它所需对象的类型。同时它还向 AbstractFactory 传递颜色信息 ColorRED / GREEN / BLUE),以便获取它所需对象的类型。

image-20240205192704328

  • 步骤1:为形状和颜色创建一个接口
public interface Shape {void draw();
}
public interface Color {void fill();
}
  • 步骤2:分别创建实现形状和颜色的实体类
//实现形状接口的实体类
public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Inside Rectangle::draw() method.");}
}public class Square implements Shape {@Overridepublic void draw() {System.out.println("Inside Square::draw() method.");}
}public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Inside Circle::draw() method.");}
}
//实现颜色接口的实体类
public class Red implements Color {@Overridepublic void fill() {System.out.println("Inside Red::fill() method.");}
}public class Green implements Color {@Overridepublic void fill() {System.out.println("Inside Green::fill() method.");}
}public class Blue implements Color {@Overridepublic void fill() {System.out.println("Inside Blue::fill() method.");}
}
  • 步骤3:为Color和Shape接口对象创建抽象类来获取工厂
public abstract class AbstractFactory {public abstract Color getColor(String color);public abstract Shape getShape(String shape);
}
  • 步骤4:创建继承AbstractFactory的工厂类,基于给定的信息生成实体类的对象
//ShapeFactory:Shape工厂
public class ShapeFactory extends AbstractFactory {@Overridepublic Shape getShape(String shapeType){if(shapeType == null){return null;}        if(shapeType.equalsIgnoreCase("CIRCLE")){return new Circle();} else if(shapeType.equalsIgnoreCase("RECTANGLE")){return new Rectangle();} else if(shapeType.equalsIgnoreCase("SQUARE")){return new Square();}return null;}@Overridepublic Color getColor(String color) {return null;}
}
//ShapeFactory:Shape工厂
public class ColorFactory extends AbstractFactory {@Overridepublic Shape getShape(String shapeType){return null;}@Overridepublic Color getColor(String color) {if(color == null){return null;}        if(color.equalsIgnoreCase("RED")){return new Red();} else if(color.equalsIgnoreCase("GREEN")){return new Green();} else if(color.equalsIgnoreCase("BLUE")){return new Blue();}return null;}
}
  • 步骤5:创建一个工厂创造器,通过传递形状或颜色信息来获取指定的工厂
public class FactoryProducer {public static AbstractFactory getFactory(String choice){if(choice.equalsIgnoreCase("SHAPE")){return new ShapeFactory();} else if(choice.equalsIgnoreCase("COLOR")){return new ColorFactory();}return null;}
}
  • 消费者:通过FactoryProducer来获取AbstracFactory,进而通过传递类型信息来获取实体类对象
public class AbstractFactoryPatternDemo {public static void main(String[] args) {//获取形状工厂AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");//获取形状为 Circle 的对象Shape shape1 = shapeFactory.getShape("CIRCLE");//调用 Circle 的 draw 方法shape1.draw();//获取形状为 Rectangle 的对象Shape shape2 = shapeFactory.getShape("RECTANGLE");//调用 Rectangle 的 draw 方法shape2.draw();//获取形状为 Square 的对象Shape shape3 = shapeFactory.getShape("SQUARE");//调用 Square 的 draw 方法shape3.draw();//获取颜色工厂AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");//获取颜色为 Red 的对象Color color1 = colorFactory.getColor("RED");//调用 Red 的 fill 方法color1.fill();//获取颜色为 Green 的对象Color color2 = colorFactory.getColor("GREEN");//调用 Green 的 fill 方法color2.fill();//获取颜色为 Blue 的对象Color color3 = colorFactory.getColor("BLUE");//调用 Blue 的 fill 方法color3.fill();}
}
  • 执行结果

    image-20240205192704328

3.优缺点

3.1优点

  • 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类进行管理;
  • 当增加一个新的产品族时不需要修改原代码,满足开闭原则。

3.2缺点

  • 当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。

4.小结

  • 工厂模式和抽象工厂的异同
    • 工厂模式和抽象工厂都是创建对象的设计模式
    • 创建对象的方式和对象的组织结构不同
      • 工厂模式式通过一个工厂类来创建一个具体的对象
      • 抽象工厂是通过一组相关的工厂来创建一组相关的对象
      • 工厂模式只适用于单一产品的创建
      • 抽象工厂适用于一组相关产品的创建

祥讲创建对象的过程:

  • 工厂模式:定义了一个用于创建对象的接口(工厂),让其具体的工厂子类决定实例化哪个类:使得一个类的实例化延迟到其子类;适用于创建的对象比较少的情况

    image-20240205192704328

  • 抽象工厂:定义了一个工厂创作器(用于创建指定的工厂,里面包含多个工厂),进而通过该工厂创建具体的产品

访问类提供一个创建一组相关或相互依赖对象的接口,且==访问类无须指定所要产品的具体类==就能得到同族的不同等级的产品的模式结构;

image-20240205192704328

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2776740.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

解析十六进制雷达数据格式:解析雷达数据类型。

以Cat62格式雷达数据为例,十六进制雷达数据部分代码: 3e0120bf7da4ffee0085 雷达数据使用2个字符(1个字节)标识,在这里是“3e”,转换为十进制数为62。 雷达数据类型父类: base_header_process…

Git简单了解

文章目录 1、Git概述2、Git下载与安装3、Git代码托管服务3.1、使用码云托管服务 1、Git概述 什么是Git Git是一个分布式版本控制工具,主要用于管理开发过程中的源代码文件(Java类、xml文件、html页面等),在软件开发过程中被广泛使…

jvm问题自查思路

本文聊一下最近处理了一些jvm的问题上,将这个排查和学习过程分享一下,看了很多资料,最终都会落地到几个工具的使用,本文主要是从文档学习、工具学习和第三方技术验证来打开认知和实践,希望有用。 一、文档 不仅知道了…

新年新展望

去年其实是收获颇丰的一年,除了工作中各项工作都得到了很大的推进,个人生活中也有很多变化,其中还拿到了功能安全工程师的证书,以及功能安全经理的证书。 展望一下2024年准备输出的内容,一个是对ISO26262的解读&#x…

力扣刷题之旅:进阶篇(五)—— 动态规划(DP)的妙用

力扣(LeetCode)是一个在线编程平台,主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目,以及它们的解题代码。 --点击进入刷题地址 引言: 在算法的世界中,动态规划&#xff…

开发JSP应用程序

开发JSP应用程序 问题陈述 TecknoSoft Pvt Ltd.公司的首席技术官(CTO)John Barrett将创建一个应用程序的任务委托给了开发团队,该应用程序应在客户访问其账户详细信息前验证其客户ID和密码。客户ID应是数字形式。John希望如果所输入的客户ID或密码不正确,应向客户显示错误…

一文带你读懂JSON模块

json模块 JSON (JavaScript Object Notation):是一个轻量级的数据交换格式模块,受javascript对象文本语法启发,但不属于JavaScript的子集。 常用方法: dump(obj,fp):将对象以字符串的形式写入文件中。 load(fp)&am…

Web项目利用EasyExcel实现Excel的导出操作

早期Java使用的一些解析,到处excel的框架存在种种问题被遗弃,现在使用阿里巴巴所提供的EasyExcel已成为一种主流,本篇将详细介绍该功能在Web项目中如何实际应用。 详细操作文档:写Excel | Easy Excel 一、项目演示 在后台管理界…

【数据结构与算法-初学者指南】【附带力扣原题】队列

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《数据结构与算法:初学者入门指南》📘&am…

作业2.8

1、选择题 1.1、以下选项中,不能作为合法常量的是 ____B______ A)1.234e04 B)1.234e0.4 C)1.234e4 D)1.234e0 1.2、以下定义变量并初始化错误的是_____D________。 A) char c1 ‘H’ ; B) char c…

《MySQL 简易速速上手小册》第9章:高级 MySQL 特性和技巧(2024 最新版)

文章目录 9.1 使用存储过程和触发器9.1.1 基础知识9.1.2 重点案例:使用 Python 调用存储过程实现用户注册9.1.3 拓展案例 1:利用触发器自动记录数据更改历史9.1.4 拓展案例 2:使用 Python 和触发器实现数据完整性检查 9.2 管理和查询 JSON 数…

【黑马程序员】程序的内存模型

文章目录 内存分区模型分区意义代码区全局区特点代码示例 栈区特点代码示例 堆区特点代码示例 new 操作符 20240209 内存分区模型 分区意义 不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程 代码区 处于程序未执行之前 程序编译后生成的…

文件绕过-Unsafe Fileuoload

文件上传基础 什么是文件上传 将客户端数据以文件形式封装通过网络协议发送到服务器端,在服务器端解析数据,最终在服务端硬盘上作为真实的文件保存。 通常一个文件以HTTP协议进行上传时,将以POST请求发送至Web服务器,Web服务器…

PWM输入输出

PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。 PWM参数 PWM 中有三个重要参数&…

C++11新特性(一)

目录 C11简介 统一的列表初始化 变量类型推导 std::initializer_list 声明 auto decltype nullptr STL的一些变化 右值引用 右值引用和左值引用 右值引用适用场景 移动构造和移动语义 对类的影响 可变参数模板 递归函数方式展开参数包 STL容器中的empalce相…

内存管理 | 进程地址空间

文章目录 1.进程地址空间的理解2.将虚拟地址转换为物理地址3.进程地址空间的设计4.进程地址空间的好处 1.进程地址空间的理解 在 前文 分享的fork创建子进程的系统调用中,一个变量接收了两个不同的返回值!通过推测也知道,那个地址绝不是真是…

基于SpringBoot的记账系统项目

点击以下链接获取源码:https://download.csdn.net/download/qq_64505944/88822660?spm1001.2014.3001.5503 Java项目-8 开发工具:IDEA/Eclipse,MySQL,Tomcat 项目框架:SpringBoot,layui 功能:可以按照类型和时间查询&#xff0c…

融资项目——获取树形结构的数据

如下图所示,下列数据是一个树形结构数据,行业中包含若干子节点。表的设计如下图,设置了一个id为1的虚拟根节点。(本树形结构带虚拟根节点共三层) 实现逻辑: 延时展示方法,先展现第二层的信息&a…

年-月-日的输入方法

大家对于输入的函数一定有所认识&#xff0c;比如c中位于 #include <iostream> 中的 cin 函数&#xff0c;这个函数输入单个十分好用&#xff0c;但是对于年月日这种较为复杂的就行不通了&#xff0c;就只能输入最前面的一个 那怎么输入像这样的年月日呢 答案就是用 scan…

清理神器CleanMyMac X 空间透镜——可视化您的磁盘空间 空间透镜有什么用

不久前&#xff0c;CleanMyMac X 发布了一个新功能&#xff1a; 空间透镜 相信有非常多的小伙伴和小编一样&#xff0c; 对这个功能一脸问号 这啥玩意儿&#xff1f;&#xff1f;&#xff1f; 今天就让我们深入了解一下&#xff0c; CleanMyMac X 的空间透镜功能。 - 更好…