秒懂设计模式--学习笔记(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 关闭该项目重新运行就可启动 解决办法二: 修改组件名称

Python容器 之 通用功能

1.切片 1.格式: 数据[起始索引:结束索引:步长 2.适用类型: 字符串(str)、列表(list)、元组(tuple) 3.说明: 通过切片操作, 可以获取数据中指定部分的内容 4.注意 : 结束索引对应的数据不会被截取到 支持正向索引和逆向索引 步长用于设置截取…

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

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

Oracle数据库中RETURNING子句

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

Plotly:原理、使用与数据可视化的未来

文章目录 引言Plotly的原理Plotly的基本使用安装Plotly创建基本图表定制图表样式 Plotly的高级特性交互式图表图表动画图表集成 结论 引言 在当今的数据驱动世界中,数据可视化已经成为了一个至关重要的工具。它允许我们直观地理解数据,发现数据中的模式…

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

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

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

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

【vuejs】vue-router 路由跳转参数传递详解和应用场景及技巧

1. Vue2 Router 路由基础 1.1 路由定义 路由定义是Vue Router中实现页面路由跳转的基础。在Vue2中,路由的定义通常在应用的入口文件或路由配置文件中进行。路由定义涉及到路径模式(path)、视图组件(component)以及一…

【数据分析思维--史上最全最牛逼】

前言: 💞💞大家好,我是书生♡,主要和大家分享一下数据分析的思维!怎么提好我们对于业务的判断是非常重要的!!!希望对大家有所帮助。 💞💞代码是你…

采煤机作业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中有两个表格,其中固定的列在一个表格中&…

【Python】优雅的快速选择 - 快速排序 - 随机快速排序

快速选择(递归实现版) 这里给出以 “leetcode215. 数组中的第K个最大元素”为例的代码。 class Solution:def findKthLargest(self, nums, k):self.nums numsn len(nums)return self.quickSelect(0,n-1,n-k)def quickSelect(self,l,r,k): # 手撸快速…

Vue3实战笔记(64)—Vue 3自定义指令的艺术:实战中的最佳实践

文章目录 前言一、一些简单的Vue3自定义指令超实用案例总结 前言 书接上文,在Vue3中,自定义指令是一种强大的工具,允许我们扩展HTML元素的功能。通过自定义指令,我们可以创建可重用的行为,并将它们绑定到任何元素上。…

订单折扣金额分摊算法|代金券分摊|收银系统|积分分摊|分摊|精度问题|按比例分配|钱分摊|钱分配

一个金额分摊的算法,将折扣分摊按比例(细单实收在总体的占比)到各个细单中。 此算法需要达到以下要求: 折扣金额接近细单总额,甚至折扣金额等于细单金额,某些时候甚至超过细单总额,要保证实收不…

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

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

每日一练 - Routing Policy节点逻辑

01 真题题目 一个 routing-policy 下可以有多个节点,不同节点号用 node 标识,每个节点下可以有多个if-match 和 apply 子句,下面哪些描述是错误的? A. 不同节点之间是“或"的关系 B. 当路由与该节点的任意一个 if-match 条件匹配失败后,系统自动转入下一节点…

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

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

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

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

8.x86游戏实战-OD详解

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