设计模式——工厂类设计模式(AI回答)

发布时间:2026/6/23 14:07:09
设计模式——工厂类设计模式(AI回答) 工厂类设计模式主要思路不是调用者new真正干活的类而是实现者在之间加了一个工厂类实现者的工厂类来new真正干活的类。开发者只要new固定的工厂类你的理解非常准确。工厂模式的核心思想就是将“对象的创建”与“对象的使用”完全解耦。让调用者直接new真正干活的类具体实现类就像买东西直接去工厂生产线盯着一样一旦生产线换了类名改了、构造函数变了调用者就得大面积修改代码。加了工厂类这个“中间商”调用者只需要跟中间商打交道即可。至于你问的“开发者只要 new 固定的工厂类吗”这个答案取决于你使用的是哪种“工厂模式”。工厂家族主要分三种它们面对的场景和new的方式各有不同1. 简单工厂模式Simple Factory—— 确实是固定的工厂如果你说的是“固定的工厂类”通常指的就是简单工厂。怎么做整个系统只有一个固定的工厂类比如ShapeFactory。怎么用开发者只需要new这个固定的工厂或者直接调用它的静态方法通过传入一个参数如字符串或枚举来决定要哪种产品。代码感觉// 开发者只需要和这一个固定工厂打交道 Worker worker SimpleFactory.createWorker(TypeA);局限如果新加了“真正干活的类”必须要修改这个固定工厂内部的if-else或switch逻辑违背了“开闭原则”对扩展开放对修改关闭。2. 工厂方法模式Factory Method—— 工厂本身也抽象了为了解决简单工厂需要频繁修改工厂类的问题工厂方法模式把工厂类自己也变成了一个接口或抽象类。怎么做每一个“真正干活的类”都有一个与之对应的“专属工厂类”比如CatWorker对应CatWorkerFactoryDogWorker对应DogWorkerFactory。怎么用这时候开发者不能只new一个固定的工厂了而是要根据业务场景new对应的具体工厂。代码感觉// 想要 A 工人得 new A 工厂 WorkerFactory factory new ConcreteWorkerFactoryA(); Worker worker factory.createWorker();意义虽然开发者要new不同的工厂但由于工厂和产品都被抽象成了接口后面的业务逻辑依然可以完全不关心具体实现。3. 抽象工厂模式Abstract Factory—— 生产一整套产品族当你的系统里“真正干活的类”不是孤立的而是成套出现的比如Windows 风格的按钮和 Windows 风格的弹窗是一套Mac 风格的按钮和 Mac 风格的弹窗是一套。怎么做一个抽象工厂定义了生产一整套产品的方法。怎么用开发者在系统初始化时选择new某一个具体的“套装工厂”比如MacFactory之后整个系统拿到的所有组件都是这个套装里的。代码感觉// 一键切换成 Mac 套装工厂 ThemeFactory factory new MacThemeFactory(); Button btn factory.createButton(); // 自动获得 Mac 按钮 Window win factory.createWindow(); // 自动获得 Mac 窗口总结与现代工程的演变回到你的问题你提到的“只new固定的工厂类”在简单工厂里表现最明显。但在现代的企业级开发例如使用 Spring 等控制反转/依赖注入框架中这个模式被推向了极致开发者连工厂类都不需要自己去new了。框架在底层充当了一个巨大的“终极工厂”开发者只需要通过注解如Autowired或Resource声明“我需要这个接口”框架就会自动把真正干活的类或者对应的工厂注入进来连new工厂的动作都省了。请详细解释工厂方法模式不用和用的区别工厂方法模式详解不用工厂方法时的问题假设你在写一个游戏地图上有不同种类的敌人// 调用方直接 new 具体类 public class Game { public void spawnEnemy(String type) { if (type.equals(orc)) { Orc orc new Orc(); orc.init(); orc.spawn(); } else if (type.equals(troll)) { Troll troll new Troll(); troll.init(); troll.spawn(); } // 新增一种敌人→ 必须来这里改代码 } }问题很直接Game类知道了太多——它知道有Orc、有Troll还知道怎么初始化每一种。每次新增敌人类型都要翻进来改if/else违反开闭原则也让测试变得复杂。用工厂方法后第一步定义产品接口public interface Enemy { void init(); void spawn(); }第二步实现具体产品public class Orc implements Enemy { Override public void init() { System.out.println(兽人初始化装备斧头); } Override public void spawn() { System.out.println(兽人出现在战场); } } public class Troll implements Enemy { Override public void init() { System.out.println(巨魔初始化装备棍棒); } Override public void spawn() { System.out.println(巨魔出现在战场); } }第三步定义抽象工厂Creatorpublic abstract class EnemySpawner { // 工厂方法声明但不实现交给子类决定 protected abstract Enemy createEnemy(); // 业务逻辑只面向 Enemy 接口不知道具体类型 public void spawnEnemy() { Enemy enemy createEnemy(); // 调工厂方法 enemy.init(); enemy.spawn(); } }第四步实现具体工厂ConcreteCreatorpublic class OrcSpawner extends EnemySpawner { Override protected Enemy createEnemy() { return new Orc(); } } public class TrollSpawner extends EnemySpawner { Override protected Enemy createEnemy() { return new Troll(); } }第五步调用方public class Game { public void startLevel(EnemySpawner spawner) { // 完全不知道、也不关心是哪种敌人 spawner.spawnEnemy(); } public static void main(String[] args) { Game game new Game(); game.startLevel(new OrcSpawner()); game.startLevel(new TrollSpawner()); } }输出兽人初始化装备斧头 兽人出现在战场 巨魔初始化装备棍棒 巨魔出现在战场现在新增一种龙Dragon只需添加两个新类Game和EnemySpawner一行不动public class Dragon implements Enemy { Override public void init() { System.out.println(龙初始化张开翅膀); } Override public void spawn() { System.out.println(龙从天而降); } } public class DragonSpawner extends EnemySpawner { Override protected Enemy createEnemy() { return new Dragon(); } }对比总结不用工厂方法用工厂方法新增产品修改已有if/else只新增两个类调用方依赖依赖所有具体类只依赖抽象接口测试难以 mock 具体产品注入任意 mock 工厂职责创建逻辑散落各处集中在各自工厂类优缺点优点遵循开闭原则调用方与具体产品解耦每种产品的创建逻辑内聚在自己的工厂里便于单独测试和替换。缺点类的数量随产品种类线性增长每增一种产品就多一个工厂类如果产品种类少且不会变化这套结构偏重直接new反而更清晰。请详细解释抽象工厂模式和工厂方法模式的区别抽象工厂 vs 工厂方法一句话区别工厂方法一个工厂生产一种产品抽象工厂一个工厂生产一族产品多种产品但风格统一用同一个场景来对比还是游戏场景但现在敌人不只是一个对象——每种阵营都有自己配套的士兵和Boss而且同一阵营的风格必须统一不能兽人阵营用了精灵Boss。工厂方法的做法工厂方法只能解决一种产品的创建。要创建士兵和Boss就得建两套独立的工厂体系// 第一套士兵工厂 abstract class SoldierSpawner { protected abstract Soldier createSoldier(); } // 第二套Boss工厂 abstract class BossSpawner { protected abstract Boss createBoss(); } class OrcSoldierSpawner extends SoldierSpawner { ... } class OrcBossSpawner extends BossSpawner { ... }问题两套工厂完全独立没有任何约束阻止你把OrcSoldierSpawner和TrollBossSpawner混着用——阵营错乱代码靠自觉维护一致性。抽象工厂的做法抽象工厂把同族产品的创建收进同一个接口从结构上保证一致性产品接口public interface Soldier { void attack(); } public interface Boss { void rageAttack(); }具体产品兽人阵营public class OrcSoldier implements Soldier { public void attack() { System.out.println(兽人士兵挥动斧头); } } public class OrcBoss implements Boss { public void rageAttack() { System.out.println(兽人Boss狂暴踩踏); } }具体产品精灵阵营public class ElfSoldier implements Soldier { public void attack() { System.out.println(精灵士兵射出箭矢); } } public class ElfBoss implements Boss { public void rageAttack() { System.out.println(精灵Boss召唤风暴); } }抽象工厂接口——这是核心把一族产品绑在一起public interface FactionFactory { Soldier createSoldier(); // 创建该阵营的士兵 Boss createBoss(); // 创建该阵营的Boss }具体工厂各阵营实现public class OrcFactory implements FactionFactory { public Soldier createSoldier() { return new OrcSoldier(); } public Boss createBoss() { return new OrcBoss(); } } public class ElfFactory implements FactionFactory { public Soldier createSoldier() { return new ElfSoldier(); } public Boss createBoss() { return new ElfBoss(); } }调用方——完全不知道具体阵营public class Game { private final Soldier soldier; private final Boss boss; // 注入工厂由工厂保证产品一族一致 public Game(FactionFactory factory) { this.soldier factory.createSoldier(); this.boss factory.createBoss(); } public void startBattle() { soldier.attack(); boss.rageAttack(); } public static void main(String[] args) { System.out.println( 兽人关卡 ); new Game(new OrcFactory()).startBattle(); System.out.println( 精灵关卡 ); new Game(new ElfFactory()).startBattle(); } }输出 兽人关卡 兽人士兵挥动斧头 兽人Boss狂暴踩踏 精灵关卡 精灵士兵射出箭矢 精灵Boss召唤风暴新增亡灵阵营新增UndeadSoldier、UndeadBoss、UndeadFactory三个类其余代码零修改。结构对比图工厂方法 抽象工厂 ───────────────── ────────────────────────── EnemySpawner FactionFactory └─ createEnemy() ├─ createSoldier() └─ createBoss() OrcSpawner OrcFactory └─ createEnemy()→Orc ├─ createSoldier()→OrcSoldier └─ createBoss()→OrcBoss TrollSpawner ElfFactory └─ createEnemy()→Troll ├─ createSoldier()→ElfSoldier └─ createBoss()→ElfBoss 一个工厂方法 1×1 一个抽象工厂 1×N 1工厂1产品 1工厂N种产品保证同族核心差异总结工厂方法抽象工厂解决的问题一种产品的创建解耦一族相关产品的创建解耦工厂接口方法数1个createXxx()多个createXxx()产品一致性无约束由工厂接口从结构上保证扩展新产品种类新增一对类即可需修改工厂接口破坏性变更扩展新产品族—新增一个工厂实现即可适用场景产品种类单一需要灵活替换产品成族出现必须保持风格统一最后一点值得注意抽象工厂的弱点是横向扩展困难——如果要给所有阵营新增一种产品比如加坐骑就必须修改FactionFactory接口所有具体工厂都得跟着改。工厂方法没有这个问题因为每种产品的工厂体系互相独立。两种模式本质上是在纵向扩展加族和横向扩展加品类之间做权衡。