抽象工厂模式
创建一系列相关对象的设计模式实现
问题
什么是抽象工厂模式?如何在 JavaScript 中实现?
解答
抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。
场景示例:跨平台 UI 组件
假设我们需要创建一套 UI 组件,支持不同的主题风格(Light / Dark)。
// 抽象产品:按钮
class Button {
render() {
throw new Error('子类必须实现 render 方法');
}
}
// 抽象产品:输入框
class Input {
render() {
throw new Error('子类必须实现 render 方法');
}
}
// 具体产品:Light 主题按钮
class LightButton extends Button {
render() {
return '<button class="btn-light">Light Button</button>';
}
}
// 具体产品:Light 主题输入框
class LightInput extends Input {
render() {
return '<input class="input-light" placeholder="Light Input" />';
}
}
// 具体产品:Dark 主题按钮
class DarkButton extends Button {
render() {
return '<button class="btn-dark">Dark Button</button>';
}
}
// 具体产品:Dark 主题输入框
class DarkInput extends Input {
render() {
return '<input class="input-dark" placeholder="Dark Input" />';
}
}
// 抽象工厂
class UIFactory {
createButton() {
throw new Error('子类必须实现 createButton 方法');
}
createInput() {
throw new Error('子类必须实现 createInput 方法');
}
}
// 具体工厂:Light 主题工厂
class LightUIFactory extends UIFactory {
createButton() {
return new LightButton();
}
createInput() {
return new LightInput();
}
}
// 具体工厂:Dark 主题工厂
class DarkUIFactory extends UIFactory {
createButton() {
return new DarkButton();
}
createInput() {
return new DarkInput();
}
}
// 使用示例
function renderUI(factory) {
const button = factory.createButton();
const input = factory.createInput();
console.log(button.render());
console.log(input.render());
}
// 切换主题只需更换工厂
const lightFactory = new LightUIFactory();
const darkFactory = new DarkUIFactory();
console.log('--- Light Theme ---');
renderUI(lightFactory);
console.log('--- Dark Theme ---');
renderUI(darkFactory);
简化版:函数式实现
// 工厂函数版本,更符合 JavaScript 风格
const createUIFactory = (theme) => {
const themes = {
light: {
createButton: () => ({
render: () => '<button class="btn-light">Light Button</button>'
}),
createInput: () => ({
render: () => '<input class="input-light" />'
})
},
dark: {
createButton: () => ({
render: () => '<button class="btn-dark">Dark Button</button>'
}),
createInput: () => ({
render: () => '<input class="input-dark" />'
})
}
};
return themes[theme] || themes.light;
};
// 使用
const factory = createUIFactory('dark');
const button = factory.createButton();
console.log(button.render()); // <button class="btn-dark">Dark Button</button>
与工厂模式的区别
// 工厂模式:创建单一产品
class ButtonFactory {
create(type) {
if (type === 'light') return new LightButton();
if (type === 'dark') return new DarkButton();
}
}
// 抽象工厂:创建一系列相关产品
class UIFactory {
createButton() { /* ... */ }
createInput() { /* ... */ }
createCheckbox() { /* ... */ }
// 保证产品之间的一致性
}
关键点
- 解决问题:创建一系列相关对象,保证产品族的一致性
- 与工厂模式区别:工厂模式创建单一产品,抽象工厂创建产品族
- 优点:切换产品族只需更换工厂,符合开闭原则
- 缺点:新增产品类型需要修改所有工厂类
- 适用场景:主题切换、跨平台 UI、数据库适配层
目录