什么是工厂方法模式?JavaScript 实现一个代理模式的示例
·
什么是工厂方法模式?
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它定义一个用于创建对象的接口(或抽象方法),但将具体对象的创建延迟到子类中。
与简单工厂模式不同,工厂方法模式不通过一个统一的工厂类创建所有对象,而是为每个产品类型对应一个具体工厂,由具体工厂负责创建对应的产品。这样,当新增产品时,无需修改现有工厂代码,只需新增产品类和对应的工厂类,更符合 “开闭原则”。
工厂方法模式的核心角色
- 抽象产品(Product):定义所有具体产品的公共接口(或父类)。
- 具体产品(ConcreteProduct):实现抽象产品接口的具体类。
- 抽象工厂(Factory):声明一个创建产品的抽象方法(工厂方法),返回抽象产品类型。
- 具体工厂(ConcreteFactory):实现抽象工厂的方法,创建并返回具体产品实例。
JavaScript 实现工厂方法模式示例:日志记录器
以下以 “日志记录器” 为例,实现工厂方法模式。需求是:支持控制台日志、文件日志两种记录方式,未来可能扩展数据库日志。通过工厂方法模式,每种日志类型对应一个具体工厂,客户端通过工厂获取日志实例。
代码实现 - javascript
// -------------- 1. 抽象产品:日志记录器基类 --------------
class Logger {
// 抽象方法:记录日志
log(message) {
throw new Error("子类必须实现 log 方法");
}
}
// -------------- 2. 具体产品:控制台日志、文件日志 --------------
// 控制台日志
class ConsoleLogger extends Logger {
log(message) {
console.log(`[Console] ${new Date().toLocaleString()}: ${message}`);
}
}
// 文件日志(模拟,实际会写入文件)
class FileLogger extends Logger {
log(message) {
console.log(`[File] ${new Date().toLocaleString()}: ${message}(已写入日志文件)`);
}
}
// -------------- 3. 抽象工厂:日志工厂接口 --------------
class LoggerFactory {
// 抽象工厂方法:创建日志记录器
createLogger() {
throw new Error("子类必须实现 createLogger 方法");
}
}
// -------------- 4. 具体工厂:控制台日志工厂、文件日志工厂 --------------
// 控制台日志工厂
class ConsoleLoggerFactory extends LoggerFactory {
createLogger() {
return new ConsoleLogger(); // 返回控制台日志实例
}
}
// 文件日志工厂
class FileLoggerFactory extends LoggerFactory {
createLogger() {
return new FileLogger(); // 返回文件日志实例
}
}
// -------------- 使用示例 --------------
// 客户端使用:通过具体工厂获取日志实例
function useLogger(loggerFactory) {
const logger = loggerFactory.createLogger();
logger.log("用户登录成功");
logger.log("数据更新完成");
}
// 场景1:使用控制台日志
const consoleFactory = new ConsoleLoggerFactory();
useLogger(consoleFactory);
// 输出:
// [Console] 2025/11/14 10:00:00: 用户登录成功
// [Console] 2025/11/14 10:00:00: 数据更新完成
// 场景2:使用文件日志
const fileFactory = new FileLoggerFactory();
useLogger(fileFactory);
// 输出:
// [File] 2025/11/14 10:00:00: 用户登录成功(已写入日志文件)
// [File] 2025/11/14 10:00:00: 数据更新完成(已写入日志文件)
// -------------- 扩展:新增数据库日志(符合开闭原则) --------------
// 新增具体产品:数据库日志
class DatabaseLogger extends Logger {
log(message) {
console.log(`[Database] ${new Date().toLocaleString()}: ${message}(已存入数据库)`);
}
}
// 新增具体工厂:数据库日志工厂
class DatabaseLoggerFactory extends LoggerFactory {
createLogger() {
return new DatabaseLogger();
}
}
// 使用新日志类型,无需修改原有代码
const dbFactory = new DatabaseLoggerFactory();
useLogger(dbFactory);
// 输出:
// [Database] 2025/11/14 10:00:00: 用户登录成功(已存入数据库)
代码说明
- 抽象产品(Logger):定义了日志记录的通用接口
log,所有具体日志类都需实现该方法。 - 具体产品(ConsoleLogger、FileLogger 等):分别实现了控制台、文件、数据库的日志记录逻辑,专注于自身功能。
- 抽象工厂(LoggerFactory):声明了抽象工厂方法
createLogger,规定所有具体工厂必须实现该方法来创建日志实例。 - 具体工厂(ConsoleLoggerFactory 等):每个工厂对应一种日志类型,通过
createLogger方法返回具体的日志实例。
工厂方法模式的优势
- 符合开闭原则:新增产品时,只需新增对应的具体产品类和具体工厂类,无需修改现有代码(如示例中新增数据库日志)。
- 单一职责:每个具体工厂只负责创建一种产品,逻辑清晰,易于维护。
- 灵活性高:客户端可通过切换具体工厂来使用不同产品,无需关心产品的创建细节。
与简单工厂模式的区别
| 维度 | 简单工厂模式 | 工厂方法模式 |
|---|---|---|
| 工厂数量 | 一个统一的工厂类创建所有产品 | 每种产品对应一个具体工厂类 |
| 扩展方式 | 需修改工厂类的判断逻辑(违反开闭) | 新增产品类和工厂类(符合开闭) |
| 复杂度 | 实现简单,适合产品类型少的场景 | 结构稍复杂,适合产品类型多的场景 |
工厂方法模式更适合产品类型多变、需要频繁扩展的场景,是对简单工厂模式的进一步抽象和优化。
更多推荐


所有评论(0)