GoF 23 种设计模式之一:工厂模式(Factory Pattern)

深入理解 GoF 工厂模式

本文记录我对 GoF(Gang of Four)工厂模式的学习过程,系统地介绍三种工厂模式的概念、优缺点及应用场景,并结合示例代码加以说明,帮助读者快速掌握这一创建型设计模式。

简介

在软件开发中,设计模式是针对常见问题的可重用解决方案。1995 年,Erich Gamma 等四位作者在《Design Patterns: Elements of Reusable Object-Oriented Software》中首次系统总结了 23 种经典设计模式,这几位作者亦被称为“GoF 四人组”。

GoF 设计模式概览

GoF 将设计模式分为三大类:

  1. 创建型(5 种):关注对象创建机制

  2. 结构型(7 种):关注类与对象的组合

  3. 行为型(11 种):关注对象间的交互

本篇重点介绍“创建型”中的三种工厂模式。

为什么选择工厂模式

  • 解耦:客户端无需了解产品的具体创建过程,只需通过工厂获取对象。

  • 职责分离:将“生产者”和“消费者”分离,便于维护与扩展。

  • 符合开闭原则:正确使用可在不修改现有代码的情况下扩展新产品。

在 Spring 框架中,BeanFactory/FactoryBean 底层大量采用了工厂模式,了解它有助于深入理解 Spring 的设计原理。

工厂模式分类

1. 简单工厂模式(Simple Factory)

非 GoF 原著模式,仅社区常用。

  • 定义:通过一个工厂类,根据传入参数决定实例化哪一种产品。

  • 角色

    • 抽象产品(Weapon

    • 具体产品(DaggerTankFighter

    • 工厂类(WeaponFactory

  • 优点:客户端调用简单,职责分离。

  • 缺点

    1. 扩展新产品时需修改工厂类,违背开闭原则。

    2. 工厂类责任过重,成为“上帝类”。

代码示例

// 抽象产品
public abstract class Weapon {
   public abstract void attack();
}

// 具体产品:匕首
public class Dagger extends Weapon {
   @Override
   public void attack() {
       System.out.println("匕首发动突刺攻击");
  }
}

// 具体产品:坦克
public class Tank extends Weapon {
   @Override
   public void attack() {
       System.out.println("坦克发射主炮");
  }
}

// 具体产品:战斗机
public class Fighter extends Weapon {
   @Override
   public void attack() {
       System.out.println("战斗机投放导弹");
  }
}

// 工厂类
public class WeaponFactory {
   public static Weapon get(String type) {
       switch (type.toUpperCase()) {
           case "DAGGER":  return new Dagger();
           case "TANK":    return new Tank();
           case "FIGHTER": return new Fighter();
           default:        throw new IllegalArgumentException("未知武器类型:" + type);
      }
  }
}

// 客户端测试
public class Client {
   public static void main(String[] args) {
       Weapon w1 = WeaponFactory.get("TANK");    w1.attack();
       Weapon w2 = WeaponFactory.get("DAGGER");  w2.attack();
       Weapon w3 = WeaponFactory.get("FIGHTER"); w3.attack();
  }
}

2. 工厂方法模式(Factory Method)

GoF 原著模式之一。

  • 定义:为每个具体产品提供一个对应的工厂类,工厂接口定义创建方法,具体工厂负责实例化对应产品。

  • 角色

    • 抽象产品(Weapon

    • 具体产品(DaggerGun

    • 抽象工厂(WeaponFactory

    • 具体工厂(DaggerFactoryGunFactory

  • 优点:符合开闭原则,增加新产品只需添加新工厂类和新产品类。

  • 缺点:产品和工厂类成对增加,类的数量成倍增长。

代码示例

// 抽象产品
public abstract class Weapon {
   public abstract void attack();
}

// 具体产品:匕首
public class Dagger extends Weapon {
   @Override public void attack() {
       System.out.println("匕首发动突刺攻击");
  }
}

// 具体产品:枪
public class Gun extends Weapon {
   @Override public void attack() {
       System.out.println("手枪开始射击");
  }
}

// 抽象工厂
public abstract class WeaponFactory {
   public abstract Weapon create();
}

// 具体工厂:生成匕首
public class DaggerFactory extends WeaponFactory {
   @Override public Weapon create() {
       return new Dagger();
  }
}

// 具体工厂:生成枪
public class GunFactory extends WeaponFactory {
   @Override public Weapon create() {
       return new Gun();
  }
}

// 客户端测试
public class Client {
   public static void main(String[] args) {
       WeaponFactory f1 = new DaggerFactory();
       WeaponFactory f2 = new GunFactory();
       f1.create().attack();
       f2.create().attack();
  }
}

3. 抽象工厂模式(Abstract Factory,了解)

GoF 原著模式之一,但 Spring 中较少直接使用。

  • 定义:提供一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。

  • 优点:保证同一产品族的一致性。

  • 缺点:增加新的产品非常困难,需修改抽象工厂接口及所有具体工厂。

小结

  • 简单工厂:易用但违背开闭;

  • 工厂方法:符合开闭,类增多;

  • 抽象工厂:家族一致,难以扩展。

三者各有取舍,实际项目中可根据需求灵活选用。Spring 框架底层广泛运用工厂方法模式,为我们提供了良好的可扩展性和可维护性。

  • 微信
  • 赶快加我聊天吧
  • QQ
  • 赶快加我聊天吧
  • weinxin
三桂

发表评论 取消回复 您未登录,登录后才能评论,前往登录