当前位置: 首页 > news >正文

设计模式 - 抽象工厂

抽象工厂是对工厂的抽象化,而不只是制造方法。

为了满足不同用户对产品的多样化需求,工厂不会只局限于生产一类产品,但是系统如果按工厂方法那样为每种产品都增加一个工厂又会造成工厂泛滥。所以,为了调和这种矛盾,抽象工厂模式提供了另一种思路,将各种产品分门别类,基于此来规划各种工厂的制造接口,最终确立产品制造的顶级规范。

一、品牌与系列

在工厂方法模式种每个实际的工厂直定义了一个工厂方法。而随着经济发展,人们对产品的需求不断升级,并逐渐走向个性化、多元化,制造业随之壮大起来。各类工厂遍地开发,能够制造的产品种类也丰富了起来,随之而来的弊端就是工厂泛滥。

针对这种情况,进行产业规划与整合,对现有工厂进行重构。

  • 可以基于产品品牌与系列进行生产线规划,按品牌分成A工厂与B工厂
  • 基于这两个品牌汽车工厂的系列生产线,如果今后产生新的C品牌汽车、D品牌汽车等,都可以沿用此种规划好的生产模式,这便是抽象工厂模式的基础数据模型。


二、产品规划

无论哪种工厂模式,都一定是基于特定的产品特性发展而来的。假如公司要开发一款星际战争游戏,战争设定在太阳系文明与外星文明之间展开,游戏兵种就可以分为人类和外星怪兽两个族。

 人类有各种军工高科技装备、外星靠血肉之躯与人类战斗。所以将兵种按照族进行划分。

兵种规划表格以列划分等级,以行划分族,一目了然,我们可以根据这个建立数据模型。

首先,我们来定义一个所有兵种的顶级父类兵种,这里我们使用抽象类,以达到属性继承给子类的目的。

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();
}

任何兵种都有攻击力、防御力、生命力、坐标方位等属性。

接下来我们将兵种按等级分类,假设同一等级的攻击力、防御力等属性值是相同的,所以初级、中级、高级兵种会分别对应三个等级的兵种类:

1. 初级兵种类 LowClassUnit

public abstract class LowClassUnit extends Unit {public LowClassUnit(int x, int y) {super(5, 2, 35, x, y);}
}

2. 中级兵种类 MidClassUnit

public abstract class MidClassUnit extends Unit {public MidClassUnit(int x, int y) {super(10, 8, 80, x, y);}
}

3. 高级兵种类 HighClassUnit

public abstract class HighClassUnit extends Unit {public HighClassUnit(int x, int y) {super(25, 30, 300, x, y);}
}

各等级兵种类都继承自兵种抽象类Unit,接下来定义具体的兵种类:

1. 海军陆战队员类 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);}
}

2. 变形坦克类 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);}
}

3. 巨型战舰类 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);}
}

如图,我们构造方法中调用了父类,并初始化了坐标属性,其攻击力、防御力和生命力已经在对应等级的父类里面初始化好了。

1. 蟑螂类 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);}
}

2. 毒液类 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);}
}

3. 猛犸类 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);}
}

至此,所有兵种类已经定义完毕,代码不是难点,重点集中在对兵种的划分上,横向划分族、纵向划分等级,利用类的抽象与继承描绘出所有的游戏角色以及他们之间的关系,同时避免了不少重复代码。


三、生产线规划

既然产品类的数据模型构建完成,相应的产品线也应该建立起来,接下来就定义这些产品的制造工厂。我们一共定义了6个兵种产品,那么每个产品都要对应一个工厂类吗?答案是否定的。

人类兵工厂是高度工具化的、怪兽靠母巢繁殖,所以应该将工厂分为两个族,并且每个族工厂有3个等级兵种的制造方法。

如此规划不但合理,而且避免了工厂类泛滥的问题。

1. 抽象兵工厂接口定义了三个等级兵种的制造标准

意味着子类工厂必须具备初级、中级、高级兵种的生产能力。

public interface AbstractFactory {LowClassUnit createLowClass(); // 初级兵种制造标准MidClassUnit createMidClass(); // 中级兵种制造标准HighClassUnit createHighClass(); // 高级兵种制造标准
}

2. HumanFactory 类

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 createLowClass() {LowClassUnit unit = new Marine(x, y);System.out.println("制造海军陆战队员成功.");return unit;}@Overridepublic MidClassUnit createMidClass() {MidClassUnit unit = new Tank(x, y);System.out.println("制造变形坦克成功.");return unit;}@Overridepublic HighClassUnit createHighClass() {HighClassUnit unit = new Battleship(x, y);System.out.println("制造巨型战舰成功.");return unit;}
}

2. AlienFactory 类

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 createLowClass() {LowClassUnit unit = new Roach(x, y);System.out.println("制造蟑螂兵成功.");return unit;}@Overridepublic MidClassUnit createMidClass() {MidClassUnit unit = new Poison(x, y);System.out.println("制造毒液兵成功.");return unit;}@Overridepublic HighClassUnit createHighClass() {HighClassUnit unit = new Mammoth(x, y);System.out.println("制造猛犸巨兽成功.");return unit;}
}

人类兵工厂与外星母巢分别实现了三个等级兵种的制造方法,其中前者由低到高分别返回海军陆战队员、变形坦克以及巨型战舰对象,后者则分别返回蟑螂兵、毒液兵以及猛犸兽对象,生产线规划非常清晰。

客户端调用

public class Client {public static void main(String[] args) {System.out.println("游戏开始……");System.out.println("双方挖矿攒钱……");// 第一位玩家选择了人类族System.out.println("工人建造人类族工厂……");AbstractFactory factory = new HumanFactory(10, 10);Unit marine = factory.createLowClass();marine.show();Unit tank = factory.createMidClass();tank.show();Unit ship = factory.createHighClass();ship.show();// 第二位玩家选择了外星怪兽族System.out.println("工蜂建造外星怪兽族工厂……");factory = new AlienFactory(200, 200);Unit roach = factory.createLowClass();roach.show();Unit poison = factory.createMidClass();poison.show();Unit mammoth = factory.createHighClass();mammoth.show();System.out.println("两族开始大混战……");marine.attack();roach.attack();poison.attack();tank.attack();mammoth.attack();ship.attack();}
}

至此,抽象工厂制造模式已经布局完成。

产品虽然繁多,但总有品牌、系列之分。基于此抽象工厂模式以品牌与系列进行全局规划,将看似杂乱无章的产品规划到不同的族系,再通过抽象工厂管理起来,分而治之,合纵连横。

需要注意的是,抽象工厂模式一定是基于产品的族系来划分布局的,其产品邪猎一定是相对固定的,固以抽象工厂来确立工业制造标准。而产品族则可以相对灵活多变,如此一来,我们就可以方便的扩展与替换族工厂,以达到灵活产出各类产品族系的目的。

-- 秒懂设计模式学习笔记

-- 抽象工厂

http://www.lqws.cn/news/487603.html

相关文章:

  • Perl 正则表达式
  • Chromium 136 编译指南 macOS篇:编译优化技巧(六)
  • 苹果芯片macOS安装版Homebrew(亲测)
  • “自动化失败归因”测试集-WhoWhen
  • RealSense 相机 | 读取IMU | 解决权限问题 | 提供示例程序
  • 【无刷电机FOC进阶基础准备】【04 clark变换、park变换、等幅值变换】
  • Python Django全功能框架开发秘籍
  • 五分钟了解@ExcelIgnoreUnannotated注解
  • Bug闭环解决之道:主流Bug追踪工具优劣对比
  • 月球上基于分段的全局定位
  • 【BFS】P9126 [USACO23FEB] Moo Route II S|普及+
  • MCU双分区方案,如何优雅地获知当前运行分区?
  • 纯血HarmonyOS5 打造小游戏实践:绘画板(附源文件)
  • 【基础篇-消息队列】——详解 RocketMQ 和 Kafka 的消息模型
  • 7.4.2B+树
  • 红帽全球副总裁曹衡康:开源AI开启企业级应用新纪元
  • 详解HarmonyOS NEXT仓颉开发语言中的全局弹窗
  • Android 中查看数据库内容方式
  • vue-23(创建用于逻辑提取的可重用组合组件)
  • Linux-系统管理
  • Java面试题027:一文深入了解数据库Redis(3)
  • 【Linux指南】文件管理高级操作(复制、移动、查找)
  • 学习Linux进程冻结技术
  • 县城消费市场的调研
  • 微算法科技(NASDAQ:MLGO)研发可信共识算法TCA,解决区块链微服务中的数据一致性与安全挑战
  • 从哈希到挑战响应,密码传输安全解析
  • 基于Qt开发的ModbusTcp主站软件开发教程​——从协议原理到工业级实现
  • python基于微信小程序的广西文化传承系统
  • Vscode自定义代码快捷方式
  • 2025年小程序地图打车的5大技术革新:实时路况预测与智能调度升级