设计模式-创建型-工厂模式
设计模式-创建型-工厂模式
1.工厂模式概述
什么是工厂模式?
工厂模式的应用将对象的创建和使用分离开,将创建对象的工厂用类方法封装。
工厂模式的作用?
工厂模式将创建对象的具体工程屏蔽隔离起来。
对象创建的具体过程有哪些:
检查类是否已经加载,类加载仅在首次使用时触发(懒加载)
内存分配,寻找内存可用块
对象初始化,设置初始值
生成的子对象实例,生成的辅助对象
显式创建对象的几种方式(工厂方法除外)
使用new关键字
反射
Class.newInstance()
或Constructor.newInstance()
对象克隆
clone()
反序列化
ObjectInputStream.readObject()
工厂模式有几类:
简单工厂
工厂方法
抽象工厂
2. 各种创建对象方式的形象类比
1.1 没有工厂(直接 new
创建)
类比: 客户要自己购买宝马车的所有零件(发动机、轮胎、座椅等),然后手动组装成一辆车。
过程:客户需要了解零件型号、组装流程,甚至需要专业工具。
代码示例:
BMWCar car = new BMWCar("X5", "Black", 3.0); // 直接实例化对象
特点:
✅ 简单直接:适合小规模、固定的对象创建。
❌ 紧耦合:客户端必须知道具体类的细节(如类名、构造参数)。
❌ 扩展困难:新增车型需修改客户端代码。
2.2 简单工厂(Simple Factory)
类比: 客户通过汽车订购中心(工厂)下单,只需告诉中心“我要一辆SUV”,工厂自动生产并交付。
过程:工厂类根据参数(如车型)决定创建哪种具体对象。
代码示例:
public class CarFactory {public static Car createCar(String type) {if ("SUV".equals(type)) return new BMW_X5();if ("Sedan".equals(type)) return new BMW_3Series();return null;} } // 客户端 Car car = CarFactory.createCar("SUV");
特点:
✅ 解耦:客户端无需知道具体类,只需依赖工厂。
❌ 违反开闭原则:新增车型需修改工厂类(如添加
if
分支)。✅ 集中管理:适合产品种类少且稳定的场景(如配置化弹窗)。
2.3 工厂方法(Factory Method)
类比: 汽车品牌(如宝马、奔驰)各自成立独立工厂,客户选择品牌后,由该品牌的工厂生产车型。
过程:抽象工厂定义创建方法,具体工厂子类实现生产逻辑。
代码示例:
// 抽象工厂 public interface CarFactory {Car createCar(); } // 具体工厂:宝马工厂 public class BMWFactory implements CarFactory {@Overridepublic Car createCar() {return new BMW_X5();} } // 具体工厂:奔驰工厂 public class MercedesFactory implements CarFactory {@Overridepublic Car createCar() {return new Mercedes_GLS();} } // 客户端 CarFactory factory = new BMWFactory(); Car car = factory.createCar();
特点:
✅ 开闭原则:新增品牌只需添加新工厂类,无需修改原有代码。
✅ 职责单一:每个工厂只负责一种品牌。
❌ 类数量增加:每新增一个产品需添加对应的工厂类。
2.4 抽象工厂(Abstract Factory)
类比: 汽车工厂不仅生产整车,还配套生产发动机、轮胎等,且同一品牌的产品风格统一(如宝马工厂生产宝马发动机+宝马轮胎)。
过程:抽象工厂定义创建一组相关对象的方法,具体工厂实现整套产品的生产。
代码示例:
// 抽象产品:发动机 public interface Engine { void start(); } // 具体产品:宝马发动机 public class BMWEngine implements Engine {@Overridepublic void start() { System.out.println("宝马发动机启动"); } } // 抽象工厂:汽车工厂 public interface CarFactory {Car createCar();Engine createEngine(); } // 具体工厂:宝马工厂 public class BMWFactory implements CarFactory {@Overridepublic Car createCar() { return new BMW_X5(); }@Overridepublic Engine createEngine() { return new BMWEngine(); } } // 客户端 CarFactory factory = new BMWFactory(); Car car = factory.createCar(); Engine engine = factory.createEngine();
特点:
✅ 产品族一致性:确保配套产品兼容(如宝马车配宝马发动机)。
✅ 扩展性强:新增品牌(如奥迪工厂)只需实现抽象工厂接口。
❌ 复杂度高:需管理多个产品族的创建逻辑。
2.5 对比总结
方式 | 核心思想 | 适用场景 | 优点 | 缺点 |
---|---|---|---|---|
无工厂 | 直接实例化对象 | 简单、临时的对象创建 | 无需设计,快速实现 | 紧耦合,难以扩展 |
简单工厂 | 集中管理对象创建逻辑 | 产品种类少且稳定 | 解耦客户端与具体类 | 新增产品需修改工厂类 |
工厂方法 | 子类决定创建哪种产品 | 需要灵活扩展产品类型 | 符合开闭原则,职责单一 | 类数量增加,结构复杂 |
抽象工厂 | 创建一组相关的产品族 | 需要配套产品且兼容性要求高 | 保证产品族一致性,扩展性强 | 实现复杂,需管理多层级关系 |
3.工厂模式的类图
根据笔记内容,以下是工厂模式的类图(使用Mermaid语法绘制):
3.1 没有工厂(直接new创建)
creates
Client
+main()
BMWCar
+BMWCar(model, color, engine)
客户要自己购买车架、车漆、发动机
客户要知道车的组装细节
优点:
无需设计,快速实现简单、临时的对象创建。
缺点:
紧耦合,难以扩展
代码臃肿
3.2 简单工厂
creates
uses
CarFactory
+createCar(type: String)
«interface»
Car
BMW_X5
BMW_3Series
Client
+main()
客户可通知工厂组装所有车辆
优点:
实现对象的创建和使用分离
通过配置文件修改具体产品
缺点:
添加新产品要修改工厂类
产品过多稳定性就差,扩展会导致性能变差
3.3 工厂方法
creates
creates
uses
«interface»
CarFactory
+createCar()
BMWFactory
+createCar()
MercedesFactory
+createCar()
«interface»
Car
BMW_X5
Mercedes_GLS
Client
+main()
客户通知具体工厂组装对应的具体产品。
优点:
具体工厂创建具体产品,不用修改工厂类
配置文件更换具体工厂
缺点:
一个产品对应一个工厂,类的数量成倍增加
3.4 抽象工厂
creates
creates
uses
«interface»
CarFactory
+createCar()
+createEngine()
BMWFactory
+createCar()
+createEngine()
«interface»
Car
BMW_X5
«interface»
Engine
+start()
BMWEngine
+start()
Client
+main()
客户通过品牌工厂生产对应的品牌产品。
优点:
一个工厂生产一组产品族产品
缺点:
增加旧品牌的产品将不符合开闭原则。
应用场景:
切换服务商:阿里云、腾讯云、华为云等。
切换主题:深色模式/浅色模式、各种主题皮肤。
4.配置文件
工厂模式在运行期往往需要“动态决定”到底创建哪一个具体产品或具体工厂,而不是在源码里写死。 把“要创建什么”这一信息从代码里剥离出来,最轻量的做法就是使用 配置文件(Properties 或 XML)。