Simple Factory Pattern
使用工厂函数统一创建不同类型的对象
问题
什么是简单工厂模式?如何在 JavaScript 中实现?
解答
简单工厂模式通过一个工厂函数,根据传入的参数决定创建哪种类型的对象,将对象的创建逻辑集中管理。
基础实现
// 产品类
class Car {
constructor(name) {
this.name = name;
this.type = 'car';
}
drive() {
console.log(`${this.name} is driving`);
}
}
class Bike {
constructor(name) {
this.name = name;
this.type = 'bike';
}
ride() {
console.log(`${this.name} is riding`);
}
}
// 简单工厂
function createVehicle(type, name) {
switch (type) {
case 'car':
return new Car(name);
case 'bike':
return new Bike(name);
default:
throw new Error(`Unknown vehicle type: ${type}`);
}
}
// 使用
const myCar = createVehicle('car', 'Tesla');
const myBike = createVehicle('bike', 'Giant');
myCar.drive(); // Tesla is driving
myBike.ride(); // Giant is riding
使用对象映射优化
// 产品类注册表
const vehicleClasses = {
car: Car,
bike: Bike,
};
// 工厂函数
function createVehicle(type, ...args) {
const VehicleClass = vehicleClasses[type];
if (!VehicleClass) {
throw new Error(`Unknown vehicle type: ${type}`);
}
return new VehicleClass(...args);
}
// 支持动态注册新类型
function registerVehicle(type, VehicleClass) {
vehicleClasses[type] = VehicleClass;
}
// 注册新类型
class Truck {
constructor(name) {
this.name = name;
}
}
registerVehicle('truck', Truck);
const myTruck = createVehicle('truck', 'Volvo');
实际应用:UI 组件工厂
// 不同类型的弹窗组件
class AlertDialog {
constructor(options) {
this.title = options.title;
this.message = options.message;
}
render() {
return `<div class="alert">${this.message}</div>`;
}
}
class ConfirmDialog {
constructor(options) {
this.title = options.title;
this.onConfirm = options.onConfirm;
this.onCancel = options.onCancel;
}
render() {
return `<div class="confirm">${this.title}<button>确定</button><button>取消</button></div>`;
}
}
class PromptDialog {
constructor(options) {
this.title = options.title;
this.placeholder = options.placeholder || '';
}
render() {
return `<div class="prompt"><input placeholder="${this.placeholder}"/></div>`;
}
}
// 弹窗工厂
const dialogTypes = {
alert: AlertDialog,
confirm: ConfirmDialog,
prompt: PromptDialog,
};
function createDialog(type, options) {
const DialogClass = dialogTypes[type];
if (!DialogClass) {
throw new Error(`Unknown dialog type: ${type}`);
}
return new DialogClass(options);
}
// 使用
const alert = createDialog('alert', { message: '操作成功' });
const confirm = createDialog('confirm', {
title: '确认删除?',
onConfirm: () => console.log('confirmed'),
});
关键点
- 封装创建逻辑:调用方无需知道具体类,只需传入类型参数
- 用对象映射替代 switch:便于扩展,支持动态注册新类型
- 适用场景:创建对象种类有限且相对固定,如 UI 组件、数据解析器
- 缺点:新增类型需修改工厂(违反开闭原则),复杂场景考虑抽象工厂模式
- 与构造函数区别:工厂可返回不同类型实例,构造函数只能返回自身实例
目录