什么是工厂模式?
工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式,在面向对象编程中,我们经常需要创建不同类型的对象,但直接使用 new
关键字创建对象可能会让代码变得臃肿、难以维护,工厂模式就是为了解决这个问题。
工厂模式的核心思想:
"不要直接暴露对象的创建逻辑,而是通过一个专门的工厂类来创建对象。"
为什么要用工厂模式?
咱们先来看一个例子,感受一下不使用工厂模式会有多麻烦。
案例:游戏角色生成器
假设我们要开发一个游戏,游戏中有不同类型的敌人:普通怪兽、boss怪兽、飞行怪兽,如果没有工厂模式,我们可能会这样写:
// 直接创建对象的方式 Enemy createEnemy(String type) { if (type.equals("normal")) { return new NormalMonster(); } else if (type.equals("boss")) { return new BossMonster(); } else if (type.equals("fly")) { return new FlyingMonster(); } else { throw new IllegalArgumentException("Invalid enemy type"); } }
这样写有什么问题呢?
- 代码重复:每次新增敌人类型,都需要修改这个方法。
- 难以维护:随着敌人类型增多,代码会变得越来越臃肿。
- 违反开闭原则:开闭原则是指对扩展开放,对修改关闭,但这里每次新增敌人类型都需要修改工厂方法,显然不符合。
工厂模式的三种类型
工厂模式其实有三种常见的实现方式,分别是:
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
下面咱们一一来看。
简单工厂模式(Simple Factory)
简单工厂模式是最基础的一种工厂模式,它通过一个工厂类来创建不同类型的对象。
结构示意图:
Client --> Factory --> ProductA, ProductB, ProductC
代码示例:
// 产品接口 public interface Enemy { void attack(); } // 具体产品类 class NormalMonster implements Enemy { @Override public void attack() { System.out.println("Normal Monster is attacking!"); } } class BossMonster implements Enemy { @Override public void attack() { System.out.println("Boss Monster is attacking!"); } } // 工厂类 class EnemyFactory { public static Enemy createEnemy(String type) { if (type.equals("normal")) { return new NormalMonster(); } else if (type.equals("boss")) { return new BossMonster(); } else { throw new IllegalArgumentException("Invalid enemy type"); } } }
优点:
- 结构简单,易于理解。
- 将对象的创建和使用分离。
缺点:
- 违反开闭原则,新增产品类型需要修改工厂类。
- 不是真正的工厂模式,只是简单工厂。
工厂方法模式(Factory Method)
工厂方法模式将创建对象的责任交给子类,也就是让子类决定到底要创建哪个产品。
结构示意图:
Client --> Factory --> ConcreteFactory1, ConcreteFactory2
代码示例:
// 产品接口 public interface Enemy { void attack(); } // 具体产品类 class NormalMonster implements Enemy { @Override public void attack() { System.out.println("Normal Monster is attacking!"); } } class BossMonster implements Enemy { @Override public void attack() { System.out.println("Boss Monster is attacking!"); } } // 工厂接口 public interface EnemyFactory { Enemy createEnemy(); } // 具体工厂类 class NormalMonsterFactory implements EnemyFactory { @Override public Enemy createEnemy() { return new NormalMonster(); } } class BossMonsterFactory implements EnemyFactory { @Override public Enemy createEnemy() { return new BossMonster(); } } // 客户端代码 public class Game { public static void main(String[] args) { EnemyFactory factory = new NormalMonsterFactory(); Enemy enemy = factory.createEnemy(); enemy.attack(); } }
优点:
- 符合开闭原则,新增产品类型不需要修改工厂类。
- 将对象的创建延迟到子类中。
缺点:
- 结构稍微复杂,需要为每个产品创建一个工厂类。
抽象工厂模式(Abstract Factory)
抽象工厂模式是工厂方法模式的升级版,它不仅可以创建单一产品,还可以创建一系列相关的产品。
结构示意图:
Client --> AbstractFactory --> ConcreteFactory1, ConcreteFactory2
代码示例:
// 产品族:怪物和武器 interface Enemy {} interface Weapon {} // 具体产品类 class NormalMonster implements Enemy {} class Sword implements Weapon {} // 具体产品类 class BossMonster implements Enemy {} class Axe implements Weapon {} // 抽象工厂 interface EnemyWeaponFactory { Enemy createEnemy(); Weapon createWeapon(); } // 具体工厂类 class NormalEnemyWeaponFactory implements EnemyWeaponFactory { @Override public Enemy createEnemy() { return new NormalMonster(); } @Override public Weapon createWeapon() { return new Sword(); } } // 具体工厂类 class BossEnemyWeaponFactory implements EnemyWeaponFactory { @Override public Enemy createEnemy() { return new BossMonster(); } @Override public Weapon createWeapon() { return new Axe(); } } // 客户端代码 public class Game { public static void main(String[] args) { EnemyWeaponFactory factory = new BossEnemyWeaponFactory(); Enemy enemy = factory.createEnemy(); Weapon weapon = factory.createWeapon(); // 使用敌人和武器 } }
优点:
- 可以创建一系列相关的产品,符合单一职责原则。
- 高度解耦,客户端不需要知道具体产品的实现。
缺点:
- 结构复杂,适用于产品种类非常多的情况。
工厂模式适用场景
场景 | 是否适合使用工厂模式 |
---|---|
创建对象的代码重复 | |
需要根据条件创建不同对象 | |
需要控制对象的创建过程 | |
产品族种类繁多 | ✅(抽象工厂模式) |
产品创建过程复杂 | ✅(简单工厂模式) |
常见问题解答
Q1:工厂模式和普通创建对象有什么区别?
A:普通创建对象直接使用 new
关键字,代码紧耦合,难以维护;工厂模式将对象创建逻辑封装起来,提高代码的可维护性和扩展性。
Q2:什么时候该用简单工厂,什么时候该用工厂方法?
A:如果产品种类不多,且不需要扩展,可以用简单工厂;如果产品种类多,或者需要灵活扩展,建议使用工厂方法或抽象工厂。
Q3:工厂模式会不会让代码变复杂?
A:对于小型项目,简单工厂已经足够;对于大型项目,工厂模式能有效管理对象创建,避免代码臃肿,过度使用也会增加复杂度,需要权衡。
工厂模式是面向对象编程中非常重要的一种设计模式,它通过将对象的创建和使用分离,提高了代码的灵活性和可维护性,无论是简单工厂、工厂方法,还是抽象工厂,它们的核心思想都是"不要直接创建对象,而是通过工厂来创建"。
在实际开发中,工厂模式广泛应用于:
- 创建数据库连接
- 创建UI控件
- 创建游戏中的各种角色和道具
- 配置文件的加载与解析
如果你正在学习设计模式,工厂模式绝对是值得掌握的第一个模式,它虽然不难,但却是理解其他设计模式的基础,希望这篇文章能帮你轻松入门工厂模式,写代码时少踩坑!
如果你有更多关于工厂模式的问题,欢迎在评论区留言,我会一一解答!😊
知识扩展阅读
在软件开发的世界里,我们常常会遇到这样的问题:当我们需要创建一个复杂的对象时,如何确保代码的可维护性、扩展性和复用性?答案可能隐藏在一个我们经常提及的设计模式之中——工厂模式,工厂模式究竟有什么魔力,能让我们的代码更加优雅地工作呢?就让我们一起探讨这个话题。
工厂模式是什么?
工厂模式是一种创建型设计模式,它提供了一种创建对象的接口,但由子类决定要实例化的类是哪一个,这样,工厂方法使一个类的实例化延迟到其子类。
工厂模式就是一个用于创建对象的“魔法盒子”,你不需要知道具体的创建过程,只需要通过这个“魔法盒子”来获取你需要的对象。
工厂模式的优点
降低耦合性
在工厂模式中,我们不再直接依赖于具体的产品类,而是依赖于抽象的产品接口或基类,这使得代码之间的耦合度降低,便于修改和维护。
提高代码的可扩展性
由于工厂模式将对象的创建逻辑集中在一个地方,因此当我们需要添加新的产品类时,只需要修改工厂类,而无需修改使用这些产品的其他代码。
代码复用性
工厂模式可以使得创建对象的逻辑被多个模块共享,从而提高代码的复用性。
工厂模式的适用场景
- 当一个类不知道它所需要的对象的类时。
- 当一个类希望由它的子类来指定它所创建的对象时。
- 当需要将对象创建的过程与实际的使用分离时。
案例说明
假设我们正在开发一个电商系统,需要处理不同类型的支付方式,如信用卡支付、支付宝支付和微信支付等。
如果我们直接在需要进行支付处理的类中创建具体的支付对象,那么当我们需要添加新的支付方式时,就必须修改这个类,这显然是不合适的。
如果我们使用工厂模式,就可以将支付对象的创建逻辑集中在一个地方,我们可以创建一个名为PaymentFactory
的工厂类,它根据传入的参数来决定创建哪种支付对象。
public interface Payment { void pay(double amount); } public class CreditCardPayment implements Payment { @Override public void pay(double amount) { // 信用卡支付的具体实现 } } public class AlipayPayment implements Payment { @Override public void pay(double amount) { // 支付宝支付的具体实现 } } public class WeChatPayment implements Payment { @Override public void pay(double amount) { // 微信支付的具体实现 } } public class PaymentFactory { public static Payment createPayment(String type) { switch (type) { case "credit_card": return new CreditCardPayment(); case "alipay": return new AlipayPayment(); case "wechat": return new WeChatPayment(); default: throw new IllegalArgumentException("Invalid payment type"); } } }
当我们需要在其他类中使用不同的支付方式时,只需要通过PaymentFactory
来创建即可:
public class OrderProcessor { public void processOrder(double amount, String paymentType) { Payment payment = PaymentFactory.createPayment(paymentType); payment.pay(amount); } }
这样,当我们需要添加新的支付方式时,只需要修改PaymentFactory
类,而无需修改OrderProcessor
类和其他使用支付方式的代码。
工厂模式的深层含义
除了上述的表面应用外,工厂模式还蕴含着更深层次的哲学意义。
它体现了“开闭原则”的思想,即对扩展开放,对修改关闭,这意味着当我们需要添加新的功能或特性时,不需要修改现有的代码,只需扩展新的代码即可。
工厂模式也体现了“依赖倒置原则”的思想,它强调依赖于抽象而不是具体实现,这意味着我们的代码不再直接依赖于具体的类或对象,而是依赖于抽象的产品接口或基类。
工厂模式还体现了“单一职责原则”的思想,它将对象的创建逻辑集中在一个地方,使得每个类只需要关注自己的职责,而不需要关心其他类的实现细节。
工厂模式就像一把神奇的钥匙,能够打开软件设计的大门,让我们能够更加优雅、灵活地处理各种复杂的问题。
通过降低耦合性、提高代码的可扩展性和复用性,工厂模式让我们能够更加轻松地应对软件开发的挑战。
工厂模式也蕴含着许多深层次的哲学思想,如开闭原则、依赖倒置原则和单一职责原则等,这些思想不仅有助于我们编写出更加优雅、可维护的代码,还能够引导我们走向更加灵活、可扩展的设计思路。
我相信在未来的软件开发中,工厂模式将会成为我们不可或缺的利器之一。
相关的知识点: