您的位置:首页 > 科技 > 能源 > 秒懂设计模式--学习笔记(5)【创建篇-抽象工厂】

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

2024/9/30 14:00:32 来源:https://blog.csdn.net/qq_28288835/article/details/140121953  浏览:    关键词:秒懂设计模式--学习笔记(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 基于此抽象工厂模式以品牌与系列进行全局规划
  • 抽象工厂模式一定是基于产品的族系划分来布局的
  • 产品系列一定是相对固定的
  • 故以抽象工厂来确立工业制造标准(各产品系列生产接口)
  • 而产品族则可以相对灵活多变

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com