【设计模式-2.4】创建型——抽象工厂模式

说明:本文介绍设计模式中,创建型设计模式的抽象工厂设计模式;

工厂模式的问题

在【设计模式-2.2】创建型——简单工厂和工厂模式这篇博文中,介绍过飞机大战游戏里,使用简单工厂和工厂模式来创建坦克、飞机、Boss对象。

在这里插入图片描述

如果对象的类型过多,我们就需要创建更多的工厂类,并且如果我们需要对对象进行分类,如按照等级分类,坦克、飞机属于低等敌人,Boss属于高等敌人;按照战斗场景分类,坦克属于陆地,飞机属于天空,Boss可在陆地或者天空。

这就需要我们对现有的工厂类进一步抽取,抽象。

抽象工厂模式

在《秒懂设计模式》这本书中,提供了一种使用场景。如下:

在这里插入图片描述

作者假设某公司需要开发一款星际战争的游戏,游戏中兵种可分为人类与外星怪兽2个族,其中每个族又可分为1级、2级和3级,不同等级的兵种,攻击力、防御力和生命值不同;

(兵种接口)

/*** 兵种抽象类*/
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();
}

(低级兵种)

/*** 低级兵种*/
public abstract class LowClassUnit extends Unit{/*** 低级兵种* @param x* @param y*/public LowClassUnit(int x, int y) {super(5, 2, 35, x, y);}
}

(中级兵种)

/*** 中级兵种*/
public abstract class MidClassUnit extends Unit{/*** 中级兵种* @param x* @param y*/public MidClassUnit(int x, int y) {super(10, 8, 80, x, y);}
}

(高级兵种)

/*** 高级兵种*/
public abstract class HighClassUnit extends Unit{/*** 高级兵种* @param x* @param y*/public HighClassUnit(int x, int y) {super(25, 30, 300, x, y);}
}

(人族,低级兵种,海军陆战队)

/*** 海军陆战队*/
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);}
}

(人族,中级兵种,变形坦克)

/*** 变形坦克*/
public class Tank extends MidClassUnit{/*** 中级兵种** @param x* @param y*/public Tank(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("变形坦克出现了,坐标为:(" + x + "," + y + ")");}@Overridepublic void attack() {System.out.println("变形坦克攻击,攻击力为:" + attack);}
}

(人族,高级兵种,巨型战舰)

/*** 巨型战舰*/
public class Battleship extends HighClassUnit{/*** 高级兵种** @param x* @param y*/public Battleship(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("巨型战舰出现了,坐标为:(" + x + "," + y + ")");}@Overridepublic void attack() {System.out.println("巨型战舰攻击,攻击力为:" + attack);}
}

(怪兽族,低级兵种,螳螂)

/*** 螳螂*/
public class Roach extends LowClassUnit{/*** 低级兵种** @param x* @param y*/public Roach(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("螳螂出现了,坐标为:(" + x + "," + y + ")");}@Overridepublic void attack() {System.out.println("螳螂攻击,攻击力为:" + attack);}
}

(怪兽组,中级兵种,毒液)

/*** 毒液*/
public class Poison extends MidClassUnit {/*** 中级兵种** @param x* @param y*/public Poison(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("毒液出现了,坐标为:(" + x + "," + y + ")");}@Overridepublic void attack() {System.out.println("毒液攻击,攻击力为:" + attack);}
}

(怪兽组,高级兵种,猛犸)

/*** 猛犸*/
public class Mammoth extends HighClassUnit {/*** 高级兵种** @param x* @param y*/public Mammoth(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("猛犸出现了,坐标为:(" + x + "," + y + ")");}@Overridepublic void attack() {System.out.println("猛犸攻击,攻击力为:" + attack);}
}

如果使用工厂模式来设计,那么需要创建6个工厂类,且这些工厂类互相没有联系,因此我们考虑使用抽象工厂模式,如下:

(抽象兵种工厂)

/*** 抽象兵种工厂*/
public interface AbstractFactory {/*** 创建低级兵种* @return*/LowClassUnit createLowClassUnit();/*** 创建中级兵种* @return*/MidClassUnit createMidClassUnit();/*** 创建高级兵种* @return*/HighClassUnit createHighClassUnit();
}

(人类兵种工厂)

/*** 人类兵种工厂*/
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;}
}

(外星怪兽兵种工厂)

/*** 外星人兵种工厂*/
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 unit = new Roach(x, y);System.out.println("制造蟑螂成功。");return unit;}@Overridepublic MidClassUnit createMidClassUnit() {MidClassUnit unit = new Poison(x, y);System.out.println("制造毒液成功。");return unit;}@Overridepublic HighClassUnit createHighClassUnit() {HighClassUnit unit = new Mammoth(x, y);System.out.println("制造猛犸象成功。");return unit;}
}

(客户端,演示人类兵种、怪兽兵种的创建)

/*** 客户端*/
public class Client {public static void main(String[] args) {System.out.println("......人类兵种工厂开始制造兵种......");// 创建人类兵种工厂AbstractFactory humanFactory = new HumanFactory(10, 10);// 创建低级兵种LowClassUnit humanLowClassUnit = humanFactory.createLowClassUnit();// 创建中级兵种MidClassUnit humanMidClassUnit = humanFactory.createMidClassUnit();// 创建高级兵种HighClassUnit humanHighClassUnit = humanFactory.createHighClassUnit();// 低级兵种展示和攻击humanLowClassUnit.show();humanLowClassUnit.attack();// 中级兵种展示和攻击humanMidClassUnit.show();humanMidClassUnit.attack();// 高级兵种展示和攻击humanHighClassUnit.show();humanHighClassUnit.attack();System.out.println("==========================================================");System.out.println("......外星人兵种工厂开始制造兵种......");// 创建外星人兵种工厂AbstractFactory alienFactory = new AlienFactory(200, 200);// 创建低级兵种LowClassUnit alienLowClassUnit = alienFactory.createLowClassUnit();// 创建中级兵种MidClassUnit alienMidClassUnit = alienFactory.createMidClassUnit();// 创建高级兵种HighClassUnit alienHighClassUnit = alienFactory.createHighClassUnit();// 低级兵种展示和攻击alienLowClassUnit.show();alienLowClassUnit.attack();// 中级兵种展示和攻击alienMidClassUnit.show();alienMidClassUnit.attack();// 高级兵种展示和攻击alienHighClassUnit.show();alienHighClassUnit.attack();}
}

以上是抽象工厂模式创建对象的过程。抽象工厂模式是对工厂模式的一种提炼,当我们需要对系统中的对象进行分类区别时,应当考虑使用抽象工厂模式。

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书,代码来自《秒懂设计模式》,略有不同。

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

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

相关文章

Java之Clonable接口和深浅拷贝

Clonable接口 我们船舰了一个人的对象,想要克隆一个一模一样的对象,可以用到object类里面的克隆方法 object不是所有类的父类吗?那为什么用person1点不出这个方法呢?可以看一下源码 这是Object类里面的clone方法的声明&#xff0…

Linux下FFmepg使用

1.命令行录一段wav,PCM数据 ffmpeg -f alsa -i hw:0,0 xxx.wav//录制 ffplay out.wav//播放ffmpeg -f alsa -i hw:0,0 -ar 16000 -channels 1 -f s16le 1.pcm ffplay -ar 16000 -channels 1 -f s16le 1.pcm -ar freq 设置音频采样率 -ac channels 设置通道 缺省为1 2.将pcm…

基于C/C++的rapidxml加载xml大文件 - 下部分

下载地址: RapidXml (sourceforge.net)https://rapidxml.sourceforge.net/ 将源码添加到自己的工程中 示例测试大文件耗时: 总共293w行数据,大概耗时不到1s。

Mr. Cappuccino的第65杯咖啡——MacOS安装Docker

MacOS安装Docker 下载Docker安装Docker查看Docker相关信息镜像加速 下载Docker Docker官网 Docker文档中心 Docker桌面版下载地址 安装Docker 查看Docker相关信息 docker --versiondocker info镜像加速 阿里云镜像加速器 "registry-mirrors": ["https://gq8…

【案例】--“特别抢购”案例

目录 一、案例背景二、技术方案思路三、技术方案具体设计3.1、表设计3.2、Java代码实现一、案例背景 A公司向供应商B公司买了一套软件产品。B公司的这套产品有多个应用系统服务【如appId1、appId2、appId3】,每个应用都有各自的业务应用场景,但都需要管理文档,那么就需要磁…

网络基础——路由协议及ensp操作

目录 一、路由器及路由表 1.路由协议: 2.路由器转发原理: 3.路由表: 二、静态路由优缺点及特殊静态路由默认路由 1.静态路由的优缺点: 2.下一跳地址 3.默认路由 三、静态路由配置 四、补充备胎 平均负载 五、补充&…

计算机网络:网络层(无分类编址CIDR、计算题讲解)

带你快速通关期末 文章目录 前言一、无分类编址CIDR简介二、构成超网三、最长前缀匹配总结 前言 我们在前面知道了分类地址,但是分类地址又有很多缺陷: B类地址很快将分配完毕!路由表中的项目急剧增长! 一、无分类编址CIDR简介 无分类域间路由选择CI…

fckeditor编辑器改造示例:增加PRE,CODE控件

查看专栏目录 Network 灰鸽宝典专栏主要关注服务器的配置,前后端开发环境的配置,编辑器的配置,网络服务的配置,网络命令的应用与配置,windows常见问题的解决等。 文章目录 修改方法:1)修改fckco…

京微齐力:基于H7的平衡控制系统(一、姿态解析)

目录 前言一、关于平衡控制系统二、实验效果三、硬件选择1、H7P20N0L176-M2H12、MPU6050 四、理论简述五、程序设计1、Cordic算法2、MPU6050采集数据3、fir&iir滤波4、姿态解算 六、资源消耗&工程获取七、总结 前言 很久之前,就想用纯FPGA做一套控制系统。可…

期末数组函数加强练习

目录 开胃菜: 第一题:求简单交错序列前N项和 第二题:最小回文数: 数组: 第一题:矩阵的对角线求和 第二题:数组插入处理 第三题:数字逆序输出 第五题:最小数和它的…

论文阅读:Lidar Annotation Is All You Need

目录 概要 Motivation 整体架构流程 技术细节 小结 概要 论文重点在探讨利用点云的地面分割任务作为标注,直接训练Camera的精细2D分割。在以往的地面分割任务中,利用Lidar来做地面分割是目前采用激光雷达方案进行自动驾驶的常见手段。来自Evocargo …

一篇文章了解Flutter Json系列化和反序列化

目录 一. 使用dart:convert实现JSON格式编解码1. 生成数据模型类2. 将JSON数据转化成数据模型类3. 数据模型类转化成JSON字符串 二、借助json_serializable实现Json编解码1.添加json_annotation、build_runner、json_serializable依赖2. 创建一个数据模型类3. 使用命令行生成JS…

819. 最常见的单词

819. 最常见的单词 Java:split() 过滤 class Solution {public String mostCommonWord(String paragraph, String[] banned) {String s paragraph.replaceAll("\\p{Punct}", " "); // 去除所有标点符号String arr[] s.split(" "…

遗传算法应用-- 栅格法机器人路径规划

文章目录 一、遗传算法1.1 编码与解码1.2 选择算子-轮盘赌法1.3 交叉算子1.4 变异算子1.5 遗传算法流程1.6 基于遗传算法的栅格法机器人路径规划 二、采用模拟退火算法改善适应度函数 一、遗传算法 遗传算法 (Genetic AIgorithm, 简称 GA)起源于对生物系统所进行的计算机模拟研…

1.3 第一个C程序

一、Dev-C的安装 下载地址:https://sourceforge.net/projects/orwelldevcpp/ 二、Dev-C简单的使用 2.1 首次打开配置 2.2 第一个程序的编辑、编译、运行 三、Hello Word程序讲解 3.1 程序框架 几乎所有的程序都需要这一段代码 3.2 输出 printf("Hello World…

workflow系列教程(4)Parallel并联任务流

往期教程 如果觉得写的可以,请给一个点赞关注支持一下 观看之前请先看,往期的博客教程,否则这篇博客没办法看懂 workFlow c异步网络库编译教程与简介 C异步网络库workflow入门教程(1)HTTP任务 C异步网络库workflow系列教程(2)redis任务 workflow系列教程(3)Series串联任务流…

AICore 带来了 Android 专属的 AI 能力,它要解决什么?采用什么架构思路?

前言 Google 最近发布的 Gemini 模型在全球引起了巨大反响,其在多模态领域的 Video demo 无比震撼。对于 Android 开发者而言,其中最振奋人心的消息莫过于 Gemini Nano 模型将内置到 Android 系统当中,并开放给开发者使用。 事实上&#xf…

【产品经理】产品专业化提升路径

产品专业化就是上山寻路,梳理一套作为产品经理的工作方法。本文作者从设计方法、三基座、专业强化、优秀产品拆解、零代码这五个方面,对产品经理的产品专业化进行了总结归纳,一起来看一下吧。 产品专业化就是上山寻路,梳理一套作为…

接口自动化测试框架【AIM】

最近在做公司项目的自动化接口测试,在现有几个小框架的基础上,反复研究和实践,搭建了新的测试框架。利用业余时间,把框架总结了下来。 AIM框架介绍 AIM,是Automatic Interface Monitoring的简称,即自动化…

c++ websocket 协议分析与实现

前言 网上有很多第三方库,nopoll,uwebsockets,libwebsockets,都喜欢回调或太复杂,个人只需要在后端用,所以手动写个; 1:环境 ubuntu18 g(支持c11即可) 第三方库:jsoncpp,openssl 2:安装 jsoncpp 读取json 配置文件 用 自动安装 网…