诗曰:
对象创建花样多,直接 new 出祸端。
工厂模式来相助,解耦创建保平安。
📖 故事
师徒四人来到"对象创建国",只见城门上写着"法宝制造中心"。
八戒一看乐了:"猴哥,你看这满街的法宝店,老猪我去弄几件趁手的兵器!"
悟空急忙拦住:"呆子!莫要乱闯!这国的规矩是------不能直接 new 对象,得走工厂!"
八戒不解:"为啥?俺老猪有钱,想买啥买啥!"
悟空笑道:"你且看这国的门道..."
🐉 踩坑打怪:耦合三魔的围剿
第一魔:硬编码之妖
八戒不信邪,冲进一家兵器铺,直接 new 了一把九齿钉耙:
java
public class Bajie {
private Weapon weapon = new NineProngedRake(); // 直接 new!
public void fight() {
weapon.attack();
}
}
谁知刚出门,就遇到"硬编码之妖"!此妖使出一招"需求变更",八戒顿时傻眼!
妖怪吼道: "八戒!国王有令,你现在要用禅杖,不用钉耙了!"
八戒慌了:"这...这可咋办?"
悟空分析: "呆子!你的武器是硬编码 new 出来的,要换武器就得改代码、重新编译!"
八戒哭道:"猴哥救命!"
第二魔:依赖纠缠怪
悟空帮八戒改了代码,继续前行。谁知又遇"依赖纠缠怪"!
java
public class TangSeng {
private WhiteHorse horse = new WhiteHorse();
private BuddhistRobes robes = new BuddhistRobes();
private BuddhistHat hat = new BuddhistHat();
// 以后每加一个依赖,就要改这里...
public void travel() {
horse.ride();
robes.wear();
hat.putOn();
}
}
妖怪使招: "依赖倒置!"
唐僧被各种依赖缠住,动弹不得!
悟空分析: "师父,你这类依赖了太多具体类!哪天要换个马,就得改你的代码!应该依赖抽象,而不是具体实现!"
第三魔:扩展封闭兽
好不容易脱身,又遇"扩展封闭兽"!
java
public class WeaponFactory {
public static Weapon createWeapon(String type) {
switch (type) {
case "golden_cudgel":
return new GoldenCudgel();
case "nine_pronged_rake":
return new NineProngedRake();
case "monk_staff":
return new MonkStaff();
// 每加一个新武器,就要改这里!
default:
throw new IllegalArgumentException("未知武器");
}
}
}
妖怪吼道: "新增武器类型!"
悟空正要加新武器,却发现要改工厂代码!
悟空皱眉: "这违反了'开闭原则'!应该对扩展开放,对修改封闭!"
⚔️ 工厂模式大法
第一式:简单工厂(一个工厂管所有)
java
public class WeaponFactory {
public static Weapon createWeapon(String type) {
switch (type) {
case "golden_cudgel":
return new GoldenCudgel();
case "nine_pronged_rake":
return new NineProngedRake();
case "monk_staff":
return new MonkStaff();
default:
throw new IllegalArgumentException("未知武器");
}
}
}
// 使用
Weapon weapon = WeaponFactory.createWeapon("golden_cudgel");
优点: 简单,客户端不用管创建细节
缺点: 违反开闭原则,加新产品要改工厂
八戒评价: "这还行,老猪我只要说'给我个钉耙',工厂就给俺造!"
第二式:工厂方法(每个产品一个工厂)
java
// 抽象工厂
public interface WeaponFactory {
Weapon createWeapon();
}
// 悟空的工厂
public class WukongWeaponFactory implements WeaponFactory {
@Override
public Weapon createWeapon() {
return new GoldenCudgel();
}
}
// 八戒的工厂
public class BajieWeaponFactory implements WeaponFactory {
@Override
public Weapon createWeapon() {
return new NineProngedRake();
}
}
// 沙僧的工厂
public class ShaSengWeaponFactory implements WeaponFactory {
@Override
public Weapon createWeapon() {
return new MonkStaff();
}
}
// 使用
WeaponFactory factory = new WukongWeaponFactory();
Weapon weapon = factory.createWeapon();
优点: 符合开闭原则,加新产品不用改现有代码
缺点: 每加一个产品就要加一个工厂类
悟空点评: "这招高明!哪天如来佛祖要加个新武器,只需新建一个工厂,不用动现有的!"
第三式:抽象工厂(产品族)
java
// 抽象工厂接口
public interface EquipmentFactory {
Weapon createWeapon();
Armor createArmor();
Mount createMount();
}
// 悟空装备工厂
public class WukongEquipmentFactory implements EquipmentFactory {
@Override
public Weapon createWeapon() {
return new GoldenCudgel();
}
@Override
public Armor createArmor() {
return new PhoenixFeatherCap();
}
@Override
public Mount createMount() {
return new SomersaultCloud();
}
}
// 八戒装备工厂
public class BajieEquipmentFactory implements EquipmentFactory {
@Override
public Weapon createWeapon() {
return new NineProngedRake();
}
@Override
public Armor createArmor() {
return new IronChainArmor();
}
@Override
public Mount createMount() {
return new BlackCloud();
}
}
// 使用
EquipmentFactory factory = new WukongEquipmentFactory();
Weapon weapon = factory.createWeapon();
Armor armor = factory.createArmor();
Mount mount = factory.createMount();
优点: 可以创建一整套配套的产品
缺点: 加新产品类型要改所有工厂
沙僧总结: "大师兄的工厂产出'悟空套装',二师兄的工厂产出'八戒套装',各成一系!"
🏆 战斗总结
| 妖怪 | 攻击方式 | 破解招式 |
|---|---|---|
| 硬编码之妖 | 需求变更 | 工厂封装创建逻辑 |
| 依赖纠缠怪 | 依赖具体类 | 依赖抽象工厂接口 |
| 扩展封闭兽 | 新增产品类型 | 工厂方法模式 |
本章要点
| 模式类型 | 特点 | 适用场景 |
|---|---|---|
| 简单工厂 | 一个工厂管所有 | 产品少,逻辑简单 |
| 工厂方法 | 每个产品一个工厂 | 产品多,需要扩展 |
| 抽象工厂 | 创建产品族 | 需要配套的产品组合 |
八戒的教训
八戒不信邪,偷偷 new 了一个九齿钉耙,结果:
java
// 编译报错!构造函数是私有的
NineProngedRake rake = new NineProngedRake(); // ❌
悟空笑道:"呆子,这国的法宝都受工厂管,你绕过工厂,当然不行!"
八戒嘟囔:"知道了...以后要啥找工厂,不自己 new 了..."
下回预告
话说师徒来到"算法变换山",遇到白骨精三次变化。每次变化,悟空都要换一种打法。如何灵活应对?
欲知后事如何,且听第三回分解!