秒懂设计模式--学习笔记(5)【创建篇-抽象工厂】

目录

      • 4、抽象工厂
          • 4.1 介绍
          • 4.2 品牌与系列(针对工厂泛滥)(**分类**)
          • 4.3 产品规划(**数据模型**)
          • 4.4 生产线规划(**工厂类**)
          • 4.5 分而治之
          • 4.6 抽象工厂模式的各角色定义如下
          • 4.7 基于此抽象工厂模式以品牌与系列进行全局规划

4、抽象工厂

4.1 介绍
  • 抽象工厂模式(Abstract Factory)是对工厂的抽象化,而不只是制造方法
  • 系统如果按工厂方法那样为每种产品都增加一个新工厂又会造成工厂泛滥
  • 抽象工厂模式提供了另一种思路,将各种产品分门别类
  • 基于此来规划各种工厂的制造接口,最终确立产品制造的顶级规范,使其与具体产品彻底脱钩
  • 抽象工厂是建立在制造复杂产品体系需求基础之上的一种设计模式
  • 在某种意义上,我们可以将抽象工厂模式理解为工厂方法模式的高度集群化升级版
  • 测试类文件
    测试类文件结构
4.2 品牌与系列(针对工厂泛滥)(分类)
  • 产品多元化 --> 工厂泛滥 --> 产业规划与整合
    • A品牌3系列 + B品牌3系列 + …
    • 这便是抽象工厂模式的基础数据模型
    • 分为品牌工厂,系列工厂
4.3 产品规划(数据模型
  • 无论哪种工厂模式,都一定是基于特定的产品特性发展而来的: 从产品建模切入(提取相同点,找出不同点)
  • 例子(星际战争游戏)
  • 分析规划(提取相同点,找出不同点)
    • 兵种:人族、怪兽族…
    • 等级:1及、2级、3级…
  • 建立数据模型
  • 兵种顶层父类
package abstractFactory.entity.abstractt;/*** 兵种抽象类**/
public abstract class Unit {/*** 攻击力*/protected int attack;/*** 防御力*/protected int defence;/*** 生命力*/protected int health;/*** 横坐标*/protected int x;/*** 纵坐标*/protected int y;public Unit(int attack, int defence, int health, int x, int y) {this.attack = attack;this.defence = defence;this.health = health;this.x = x;this.y = y;}/*** 展示:绘制到图上 (抽象方法交由子类实现)*/public abstract void show();/*** 攻击(抽象方法交由子类实现)*/public abstract void attack();
}
  • 兵种等级: 各等级兵种类都继承自兵种抽象类Unit,它们对应的攻击力、防御力及生命力也各不相同
    • 初级兵种类LowClassUnit
    • 中级兵种类MidClassUnit
    • 高级兵种类HighClassUnit
package abstractFactory.entity.abstractt;
/*** 初级兵种类**/
public abstract class LowClassUnit extends Unit{public LowClassUnit( int x, int y) {super(5, 2, 35, x, y);}
}
package abstractFactory.entity.abstractt;
/*** 中级兵种类**/
public abstract class MidClassUnit extends Unit {public MidClassUnit( int x, int y) {super(10, 8, 80, x, y);}
}
package abstractFactory.entity.abstractt;
/*** 高级兵种类**/
public abstract class HighClassUnit extends Unit {public HighClassUnit( int x, int y) {super(25, 30, 300, x, y);}
}
  • 定义具体的兵种类
    • 海军陆战队员类Marine
    • 变形坦克类Tank
    • 巨型战舰类Battleship
    • 蟑螂类Roach
    • 毒液类Poison
    • 猛犸类Mammoth
package abstractFactory.entity.product;
import abstractFactory.entity.abstractt.LowClassUnit;
/*** 海军陆战队员类Marine**/
public class Marine extends LowClassUnit {public Marine(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("士兵出现在坐标:[" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("士兵用机关枪射击,攻击力:" + attack);}
}
package abstractFactory.entity.product;
import abstractFactory.entity.abstractt.MidClassUnit;
/*** 变形坦克类Tank**/
public class Tank extends MidClassUnit {public Tank(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("坦克出现在坐标:[" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("坦克用炮轰击,攻击力:" + attack);}
}
package abstractFactory.entity.product;
import abstractFactory.entity.abstractt.HighClassUnit;
/*** 巨型战舰类Battleship**/
public class Battleship extends HighClassUnit {public Battleship(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("战舰出现在坐标:[" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("战舰用激光炮打击,攻击力:" + attack);}
}
package abstractFactory.entity.product;
import abstractFactory.entity.abstractt.LowClassUnit;
/*** 蟑螂类Roach**/
public class Roach extends LowClassUnit {public Roach(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("蟑螂兵出现在坐标:[" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("蟑螂兵用爪子挠,攻击力:" + attack);}
}
package abstractFactory.entity.product;
import abstractFactory.entity.abstractt.MidClassUnit;
/*** 毒液类Poison**/
public class Poison extends MidClassUnit {public Poison(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("毒液兵出现在坐标:[" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("毒液兵用毒液喷射,攻击力:" + attack);}
}
package abstractFactory.entity.product;
import abstractFactory.entity.abstractt.HighClassUnit;
/*** 猛犸类Mammoth**/
public class Mammoth extends HighClassUnit {public Mammoth(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("猛犸巨兽出现在坐标:[" + x + "," + y + "]");}@Overridepublic void attack() {System.out.println("猛犸巨兽用獠牙顶,攻击力:" + attack);}
}
  • 所有兵种类已定义完毕,代码不是难点,重点集中在对兵种的划分上
  • 横向划分族,纵向划分等级(系列),利用类的抽象与继承描绘出所有的游戏角色以及它们之间的关系,同时避免了不少重复代码
4.4 生产线规划(工厂类
  • 数据模型构建完成,定义工厂,建立生产线
    • 定义了6个兵种产品(数据模型):实体
    • 可分为2个工厂:人族、怪兽族
    • 3个制造标准:3个等级
  • 定义抽象工厂接口:
    • 3个制造标准方法
package abstractFactory.factory;import abstractFactory.entity.abstractt.HighClassUnit;
import abstractFactory.entity.abstractt.LowClassUnit;
import abstractFactory.entity.abstractt.MidClassUnit;/*** 定义抽象工厂接口 : 抽象兵工厂接口*      抽象兵工厂接口定义了3个等级兵种的制造标准, 这意味着子类工厂必须具备初级、中级、高级兵种的生产能力**/
public interface AbstractFactory {/*** 初级兵种制造标准* @return*/LowClassUnit createLowClassUnit();/*** 中级兵种制造标准* @return*/MidClassUnit createMidClassUnit();/*** 高级兵种制造标准* @return*/HighClassUnit createHighClassUnit();
}
  • 工厂类实现
package abstractFactory.factory.impl;import abstractFactory.entity.abstractt.HighClassUnit;
import abstractFactory.entity.abstractt.LowClassUnit;
import abstractFactory.entity.abstractt.MidClassUnit;
import abstractFactory.entity.product.Battleship;
import abstractFactory.entity.product.Marine;
import abstractFactory.entity.product.Tank;
import abstractFactory.factory.AbstractFactory;
/*** 人类兵工厂**/
public class HumanFactory implements AbstractFactory {/*** 横坐标*/private int x;/*** 纵坐标*/private int y;public HumanFactory(int x, int y) {this.x = x;this.y = y;}@Overridepublic LowClassUnit createLowClassUnit() {LowClassUnit unit = new Marine(x, y);System.out.println("制造海军陆战队员成功。");return unit;}@Overridepublic MidClassUnit createMidClassUnit() {MidClassUnit unit = new Tank(x, y);System.out.println("制造变形坦克成功。");return unit;}@Overridepublic HighClassUnit createHighClassUnit() {HighClassUnit unit = new Battleship(x, y);System.out.println("制造巨型战舰成功。");return unit;}
}
package abstractFactory.factory.impl;import abstractFactory.entity.abstractt.HighClassUnit;
import abstractFactory.entity.abstractt.LowClassUnit;
import abstractFactory.entity.abstractt.MidClassUnit;
import abstractFactory.entity.product.Mammoth;
import abstractFactory.entity.product.Poison;
import abstractFactory.entity.product.Roach;
import abstractFactory.factory.AbstractFactory;/*** 外星母巢(工厂)**/
public class AlienFactory implements AbstractFactory {private int x;private int y;public AlienFactory(int x, int y) {this.x = x;this.y = y;}@Overridepublic LowClassUnit createLowClassUnit() {LowClassUnit roach = new Roach(x, y);System.out.println("制造蟑螂兵成功。");return roach;}@Overridepublic MidClassUnit createMidClassUnit() {MidClassUnit poison = new Poison(x, y);System.out.println("制造毒液兵成功。");return poison;}@Overridepublic HighClassUnit createHighClassUnit() {HighClassUnit mammoth = new Mammoth(x, y);System.out.println("制造猛犸巨兽成功。");return mammoth;}
}
  • 生产线规划非常清晰
    • 人类兵工厂与外星母巢分别实现了3个等级兵种的制造方法
    • 其中前者由低到高分别返回海军陆战队员、变形坦克以及巨型战舰对象,
    • 后者则分别返回蟑螂兵、毒液兵以及猛犸巨兽对象
  • 测试使用
    • 抽象兵工厂接口引用了人类兵工厂实现
    • 调用3个等级的制造方法分别得到人类族的对应兵种
    • 将抽象兵工厂接口引用替换为外星母巢实现
    • 制造出的兵种变为3个等级的外星怪兽族兵种
    • 如果玩家需要一个新族加入,我们可以在此模式之上去实现一个新的族工厂并实现3个等级的制造方法
    • 工厂一经替换即可产出各系列产品兵种,且无须改动现有代码,良好的可扩展性
    • 这就是一套拥有完备生产模式的标准化工业系统所带来的好处
package abstractFactory;import abstractFactory.entity.abstractt.HighClassUnit;
import abstractFactory.entity.abstractt.LowClassUnit;
import abstractFactory.entity.abstractt.MidClassUnit;
import abstractFactory.entity.abstractt.Unit;
import abstractFactory.factory.AbstractFactory;
import abstractFactory.factory.impl.AlienFactory;
import abstractFactory.factory.impl.HumanFactory;
/*** 测试客户端类**/
public class Client {/***  打印结果*      游戏开始......*      双方挖掘攒钱......*      建造人类族工厂.......*      制造海军陆战队员成功。*      士兵出现在坐标:[10,10]*      制造变形坦克成功。*      坦克出现在坐标:[10,10]*      制造巨型战舰成功。*      战舰出现在坐标:[10,10]*      建造外星怪兽族工厂*      制造蟑螂兵成功。*      蟑螂兵出现在坐标:[200,200]*      制造毒液兵成功。*      毒液兵出现在坐标:[200,200]*      制造猛犸巨兽成功。*      猛犸巨兽出现在坐标:[200,200]*      两族开始混战......*      士兵用机关枪射击,攻击力:5*      蟑螂兵用爪子挠,攻击力:5*      毒液兵用毒液喷射,攻击力:10*      坦克用炮轰击,攻击力:10*      猛犸巨兽用獠牙顶,攻击力:25*      战舰用激光炮打击,攻击力:25* @param args*/public static void main(String[] args) {System.out.println("游戏开始......");System.out.println("双方挖掘攒钱......");// 第一位玩家选择了人类族System.out.println("建造人类族工厂.......");// 抽象兵工厂接口引用了人类兵工厂实现AbstractFactory factory = new HumanFactory(10, 10);Unit marine = factory.createLowClassUnit();marine.show();Unit tank = factory.createMidClassUnit();tank.show();Unit ship = factory.createHighClassUnit();ship.show();// 第二位万家选择了外星怪兽族System.out.println("建造外星怪兽族工厂");/*** 抽象兵工厂接口引用替换为外星母巢实现* 工厂一经替换即可产出各系列产品兵种,且无须改动现有代码,良好的可扩展性*/factory = new AlienFactory(200, 200);Unit roach = factory.createLowClassUnit();roach.show();Unit poison = factory.createMidClassUnit();poison.show();Unit mammoth = factory.createHighClassUnit();mammoth.show();System.out.println("两族开始混战......");marine.attack();roach.attack();poison.attack();tank.attack();mammoth.attack();ship.attack();}
}
4.5 分而治之
  • 抽象工厂制造模式已经布局完成,各工厂可以随时大规模投入生产活动了
  • 我们还可以进一步,再加一个“制造工厂的工厂”来决定具体让哪个工厂投入生产活动
  • 此时客户端就无须关心工厂的实例化过程了,直接使用产品就可以了
  • 这也是抽象工厂可以被视为“工厂的工厂”的原因
  • 与工厂方法模式不同,抽象工厂模式能够应对更加复杂的产品族系,它更类似于一种对“工业制造标准”的制定与推行
    • 各工厂实现都遵循此标准来进行生产活动
    • 工厂类划分产品族(工厂类)
    • 制造方法划分产品系列(数据模型)
    • 达到无限扩展产品的目的
4.6 抽象工厂模式的各角色定义如下
  • 产品系列的抽象类:
    • AbstractProduct1、AbstractProduct2(抽象产品1、抽象产品2)
    • 一系产品与二系产品分别代表同一产品族多个产品系列,对应本章例程中的初级、中级、高级兵种抽象类
  • 继承自抽象产品的产品实体类(数据模型)
    • ProductA1、ProductB1、ProductA2、ProductB2(产品A1、产品B1、产品A2、产品B2)
    • 其中ProductA1与ProductB1代表A族产品与B族产品的同一产品系列,类似于例中人类族与外星怪兽族的初级兵种
  • 抽象工厂接口(AbstractFactory)
    • 各族工厂的高层抽象,可以是接口或者抽象类
    • 抽象工厂对各产品系列的制造标准进行规范化定义,但具体返回哪个族的产品由具体族工厂决定,它并不关心。
  • 工厂实现类:
    • ConcreteFactoryA、ConcreteFactoryB(工厂A实现、工厂B实现)
    • 继承自抽象工厂的各族工厂,需实现抽象工厂所定义的产品系列制方法,可以扩展多个工厂实现。
    • 对应本章例程中的人类兵工厂与外星母巢
  • Client(客户端):
    • 产品的使用者,只关心制造出的产品系列,具体是哪个产品族由工厂决定
4.7 基于此抽象工厂模式以品牌与系列进行全局规划
  • 抽象工厂模式一定是基于产品的族系划分来布局的
  • 产品系列一定是相对固定的
  • 故以抽象工厂来确立工业制造标准(各产品系列生产接口)
  • 而产品族则可以相对灵活多变

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue启动时的错误

解决办法一:在vue.config.js中直接添加一行代码 lintOnSave:false 关闭该项目重新运行就可启动 解决办法二: 修改组件名称

配音软件有哪些?分享五款超级好用的配音软件

随着嫦娥六号的壮丽回归,举国上下都沉浸在这份自豪与激动之中。 在这样一个历史性的时刻,我们何不用声音记录下这份情感,让这份记忆以声音的形式流传? 无论是制作视频分享这份喜悦,还是创作音频讲述探月故事&#xff…

Oracle数据库中RETURNING子句

RETURNING子句允许您检索插入、删除或更新所修改的列(以及基于列的表达式)的值。如果不使用RETURNING,则必须在DML语句完成后运行SELECT语句,才能获得更改列的值。因此,RETURNING有助于避免再次往返数据库,…

CXL-GPU: 全球首款实现百ns以内的低延迟CXL解决方案

数据中心在追求更高性能和更低总拥有成本(TCO)的过程中面临三大主要内存挑战。首先,当前服务器内存层次结构存在局限性。直接连接的DRAM与固态硬盘(SSD)存储之间存在三个数量级的延迟差异。当处理器直接连接的内存容量…

VideoPrism——探索视频分析领域模型的算法与应用

概述 论文地址:https://arxiv.org/pdf/2402.13217.pdf 视频是我们观察世界的生动窗口,记录了从日常瞬间到科学探索的各种体验。在这个数字时代,视频基础模型(ViFM)有可能分析如此海量的信息并提取新的见解。迄今为止,…

采煤机作业3D虚拟仿真教学线上展示增强应急培训效果

在化工行业的生产现场,安全永远是首要之务。为了加强从业人员的应急响应能力和危机管理能力,纷纷引入化工行业工艺VR模拟培训,让应急演练更加生动、高效。 化工行业工艺VR模拟培训软件基于真实的厂区环境,精确还原了各类事件场景和…

医疗器械FDA | 医疗器械软件如何做源代码审计?

医疗器械网络安全测试https://link.zhihu.com/?targethttps%3A//www.wanyun.cn/Support%3Fshare%3D24315_ea8a0e47-b38d-4cd6-8ed1-9e7711a8ad5e 医疗器械源代码审计是一个确保医疗器械软件安全性和可靠性的重要过程。以下是医疗器械源代码审计的主要步骤和要点,以…

Vue3 sortablejs 表格拖拽后,表格无法更新的问题处理

实用sortablejs在vue项目中实现表格行拖拽排序 你可能会发现,表格排序是可以实现,但是我们基于数据驱动的vue中关联的数据并没有发生变化, 如果你的表格带有列固定(固定列实际上在dom中有两个表格,其中固定的列在一个表格中&…

游泳哪个牌子好?6大游泳耳机选购技巧总结分享

游泳耳机作为水上运动爱好者和游泳专业人士的必备装备,不仅要能够抵御水的侵入,还要提供清晰的音质和舒适的佩戴体验。在市面上,不同品牌的游泳耳机琳琅满目,选择起来可能会令人头疼。本文旨在为您提供一份详尽的游泳耳机选购指南…

Gemma轻量级开放模型在个人PC上释放强大性能,让每个桌面秒变AI工作站

Google DeepMind团队最近推出了Gemma,这是一个基于其先前Gemini模型研究和技术的开放模型家族。这些模型专为语言理解、推理和安全性而设计,具有轻量级和高性能的特点。 Gemma 7B模型在不同能力领域的语言理解和生成性能,与同样规模的开放模型…

名企专访|对抗价格内卷,格行随身WiFi如何持续三年爆火引领潮流

近期要是问网红达人最喜欢带货的单品是什么?那一定有格行随身WiFi的一席之地。能聚集了如此多的明星达人,仅仅是一句带货收益高显然无法说服大家。显然这里面还有着不为人知的秘密,先锋财经特意专访了格行随身WiFi的创始人刘永先先生&#xf…

8.x86游戏实战-OD详解

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 上一个内容:7.x86游戏实战-C实现跨进程读写-跨进程写内存 工具下载:下载 OllyI…

嵌入式Linux之Uboot简介和移植

uboot简介 uboot 的全称是 Universal Boot Loader,uboot 是一个遵循 GPL 协议的开源软件,uboot是一个裸机代码,可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、USB 等高级功能。 也就是说,可以在没有系统的情况…

[我靠升级逆袭成为大师]韩漫日漫无删减完整版,免费在线观看漫画

[我靠升级逆袭成为大师]韩漫日漫无删减完整版,免费在线观看漫画 不能多说,怕审-核不过,自己看图吧。 目前统计【统计日期:2024-07-03】: 完结的有:420部。 连载的有:308部,持续更…

python库(1):Nuitka库

1 Nuitka介绍 Nuitka是一个 Python 解释器的替代品,支持CPython提供的代码,可编译 Python 代码到 C 程序,并使用 libpython 来执行这些代码,就像 CPython 一样。 这让你可以在没有安装 Python 的环境中运行 Python 程序&#xf…

AC7801时钟配置流程

一 默认配置 在启动文件中,已经对时钟进行了初始化,默认按外部8M晶振,配置系统时钟为48MHZ,APB为系统时钟的2分频,为24MHZ。在system_ac780x.c文件中,可以找到下面这个系统初始化函数,里面有Se…

前端修改audio背景色

1.查看浏览器设置Show user agent shadow DOM是否打开 2.打开可以查看audio Dom /** 去掉默认的背景颜色 */ audio::-webkit-media-controls-enclosure{background-color:unset; } 3.效果图

基于SpringBoot校园外卖配送系统设计和实现(源码+LW+调试文档+讲解等)

💗博主介绍:✌全网粉丝10W,CSDN作者、博客专家、全栈领域优质创作者,博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,…

揭秘电子世界的双雄:模拟电路与数字电路的精彩对决!

数字电路与模拟电路,这两者在电子工程领域可谓是两大基石,各有千秋,各自发挥着不可或缺的作用。下面,我们就来详细探讨一下它们之间的主要区别。 1. 信号类型与处理 模拟电路:处理的是连续变化的信号,就像…

一键恢复短信,4个方法,轻松找回iPhone数据!

在日常生活和工作中,短信往往承载着重要的信息和回忆。然而,意外删除、系统故障或手机更换等情况都可能导致短信丢失,这让很多iPhone用户感到困扰。 好消息是,您并不需要担心这些数据无法找回。如今,一键恢复短信的方…