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

news/2024/11/20 4:29:08/

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

工厂模式的问题

在【设计模式-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.ppmy.cn/news/1273523.html

相关文章

MySQL_13.InonDB表空间

InnoDB 表空间介绍以及管理 1.mysql表空间类型 system tablespace 系统表空间 file-per-table tablespace 独立表空间 temporary tablespace 临时表空间 undo tablespace UNDO表空间 general tablespace…

开源 LLM 微调训练指南:如何打造属于自己的 LLM 模型

一、介绍 今天我们来聊一聊关于LLM的微调训练,LLM应该算是目前当之无愧的最有影响力的AI技术。尽管它只是一个语言模型,但它具备理解和生成人类语言的能力,非常厉害!它可以革新各个行业,包括自然语言处理、机器翻译、…

垃圾回收 (GC) 在 .NET Core 中是如何工作的?

提起GC大家肯定不陌生,但是让大家是说一下GC是怎么运行的,可能大多数人都不太清楚,这也很正常,因为GC这东西在.NET基本不用开发者关注,它是依靠程序自动判断来释放托管堆的,我们基本不需要主动调用Collect(…

【Java基础】HashMap 原理

文章目录 1、HashMap 设置值的原理2、HashMap 获取值原理3、HashMap Hash优化4、HashMap 寻址优化5、HashMap 是如何解决Hash冲突的?5.1 get数据的时候,如果定位到指定位置的元素是一个链表,怎么办呢?5.2 红黑树 6、数组扩容6.1 数…

数据仓库与数据挖掘小结

更加详细的只找得到pdf版本 填空10分 判断并改错10分 计算8分 综合20分 客观题 填空10分 判断并改错10分--错的要改 mooc中的--尤其考试题 名词解释12分 4个,每个3分 经常碰到的专业术语 简答题40分 5个,每道8分 综合 画roc曲线 …

什么是计算机网络?计算机网络基础知识

1.网络的组成部分:由主机,路由器,交换机等组成 2.网络结构:网络的网络 3.信息交换方式:电路交换和分组交换 4.网络分层:分清职责,物理层,链路层,网络层,运…

SpringBoot 整合 ExcelEasy

ExcelEasy 是一个基于 Spring Boot 的 Excel 导入导出框架&#xff0c;它提供了简单易用的 API 来操作 Excel 文件&#xff0c;可以轻松实现 Excel 的导入导出。 1. 添加依赖 在 pom.xml 文件中添加 ExcelEasy 的依赖&#xff1a; <dependency><groupId>com.ali…

Linux 之 性能优化

uptime $ uptime -p up 1 week, 1 day, 21 hours, 27 minutes$ uptime12:04:11 up 8 days, 21:27, 1 user, load average: 0.54, 0.32, 0.23“12:04:11” 表示当前时间“up 8 days, 21:27,” 表示运行了多长时间“load average: 0.54, 0.32, 0.23”“1 user” 表示 正在登录…