前言
在平时开发过程中,如果遇到需要创建多个配置相似的对象,我们普遍想到的都是使用构造函数来解决,这种方式简单直观,有着清晰的继承体系,特别适合面向对象编程,但是不可避免的必须使用 new
关键字,否则 this
指向全局对象(如 window
),导致隐蔽的 Bug。而 new
和 this
的关键字依赖又导致原型链的复杂性增加,难以实现私有变量。
这在我们需要灵活创建多个配置相似对象同时实现真正的封装和私有状态还要避免类继承的局限性时,使用构造函数已经很难满足我们的需求,试想一下当你在封装组件时遇到响应式丢失、类继承导致的重构困难时,就不可避免的走向对
工厂模式
也因此工厂模式(Factory Pattern)这种创建型的设计模式出现了,它的核心思想是 将对象的创建逻辑封装在一个函数或类中,而不是直接通过 new
或字面量手动创建。通过这种方式,可以实现 对象创建的集中管理、解耦代码,并支持 动态生成不同类型的对象,这 些特性完美契合函数式编程的理念,即无副作用、纯函数 和 不可变性。
实现
而为了实现工厂模式,我们需要封装创建过程,也就是通过一个函数,根据输入参数返回不同对象,可以发现工厂模式它就像流水线一样批量生产对象,不同于传统的类或构造函数,它通过普通函数返回新对象的方式实现对象创建。
也因此工厂模式本质是通过一个普通函数,在内部构造对象并返回,无需 new
关键字调用。
既然提到了函数,那么在工厂模式中函数又分为两种,即工厂函数和函数工厂,虽然它们的名字非常相似,但是侧重点不同,可以理解为 同一设计模式的不同应用场景。
工厂函数(Factory Function)
工厂函数是一种用于创建并返回对象的函数,它的核心思想是 封装对象的创建过程,提供一种更灵活、可复用的对象生成方式,与传统的构造函数相比,工厂函数不依赖 new
关键字,而是直接通过函数调用来生成对象。
在 JavaScript 中,工厂函数并不是一种官方的语言特性,而是一种被广泛使用的 设计模式。
工厂函数:返回一个对象
function createUser(name) {
return {
name,
greet() {
console.log(`Hi, I'm ${name}!`);
},
};
}
const user = createUser("Alice");
user.greet(); // "Hi, I'm Alice!"
函数工厂(Function Factory)
函数工厂是一种通过函数生成并返回其他函数的设计模式,它通过闭包和参数化机制,动态创建具有特定行为的函数。在 JavaScript 中,函数工厂常用于 逻辑复用、动态配置 和 上下文隔离
函数工厂:返回一个函数
function createMultiplier(factor) {
return function (x) {
return x * factor;
};
}
const double = createMultiplier(2);
console.log(double(5)); // 10
对比
术语 | 目标 | 返回值类型 | 用途场景 |
---|---|---|---|
工厂函数 | 创建对象 | 对象(Object) | 生成结构相 似的对象 |
函数工厂 | 创建函数 | 函数(Function) | 动态生成不同行为的函数 |
两者都是 工厂模式 的具体实现,而使用哪种则取决于具体的场景,也因此接下来我会将这两种函数都统称为工厂函数。
与传统方式的对比
1. 构造函数方式
function User(name) {
this.name = name
}
User.prototype.login = function() {
console.log(`${this.name} logged in`)
}
const user = new User('Charlie')
2. 类语法
class User {
constructor(name) {
this.name = name
}
login() {
console.log(`${this.name} logged in`)
}
}
const user = new User('David')
3. 工厂函数方法
function createUser(name) {
return {
name, // 等价于 name: name
login() { // 直接定义方法
console.log(`${this.name} logged in`)
}
}
}
// 使用方式
const user = createUser('Charlie') // 不需要new关键字