Search K
Appearance
Appearance
📊 SEO元描述:2024年最新JavaScript建造者模式教程,详解复杂对象构建、链式调用实现、建造者模式应用。包含完整实战案例,适合前端开发者掌握创建型设计模式。
核心关键词:JavaScript建造者模式2024、建造者设计模式、复杂对象构建、链式调用实现、JavaScript设计模式、对象构建模式
长尾关键词:JavaScript建造者模式怎么实现、复杂对象构建最佳实践、链式调用设计模式、JavaScript对象构建器、前端建造者模式应用
通过本节JavaScript建造者模式完整指南,你将系统性掌握:
建造者模式是什么?这是创建型设计模式中专门处理复杂对象构建的重要模式。建造者模式(Builder Pattern)是指将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示的设计模式,也是优雅API设计的核心技术。
💡 设计模式建议:建造者模式特别适用于需要创建复杂对象、有多个可选参数、或者需要分步骤构建的场景,是现代JavaScript库和框架中广泛使用的模式。
建造者模式通过分步骤的方式构建复杂对象,每个步骤负责设置对象的特定属性或配置。
// 🎉 基础建造者模式实现
// 复杂产品类 - HTTP请求配置
class HttpRequest {
constructor() {
this.url = '';
this.method = 'GET';
this.headers = {};
this.params = {};
this.data = null;
this.timeout = 5000;
this.retries = 0;
this.interceptors = {
request: [],
response: []
};
this.cache = false;
this.credentials = 'same-origin';
this.responseType = 'json';
}
// 执行请求
async execute() {
console.log('Executing HTTP request with config:', this.getConfig());
// 应用请求拦截器
let config = this.getConfig();
for (const interceptor of this.interceptors.request) {
config = await interceptor(config);
}
try {
// 模拟HTTP请求
const response = await this.simulateRequest(config);
// 应用响应拦截器
let processedResponse = response;
for (const interceptor of this.interceptors.response) {
processedResponse = await interceptor(processedResponse);
}
return processedResponse;
} catch (error) {
if (this.retries > 0) {
console.log(`Request failed, retrying... (${this.retries} retries left)`);
this.retries--;
return this.execute();
}
throw error;
}
}
async simulateRequest(config) {
// 模拟网络延迟
await new Promise(resolve => setTimeout(resolve, 100));
// 模拟响应
return {
status: 200,
statusText: 'OK',
data: { message: 'Request successful', config },
headers: { 'content-type': 'application/json' }
};
}
getConfig() {
return {
url: this.url,
method: this.method,
headers: this.headers,
params: this.params,
data: this.data,
timeout: this.timeout,
cache: this.cache,
credentials: this.credentials,
responseType: this.responseType
};
}
}
// 建造者类
class HttpRequestBuilder {
constructor() {
this.request = new HttpRequest();
}
// 设置URL
url(url) {
this.request.url = url;
return this; // 返回this支持链式调用
}
// 设置HTTP方法
method(method) {
this.request.method = method.toUpperCase();
return this;
}
// 设置请求头
header(key, value) {
this.request.headers[key] = value;
return this;
}
// 批量设置请求头
headers(headers) {
Object.assign(this.request.headers, headers);
return this;
}
// 设置查询参数
param(key, value) {
this.request.params[key] = value;
return this;
}
// 批量设置查询参数
params(params) {
Object.assign(this.request.params, params);
return this;
}
// 设置请求体数据
data(data) {
this.request.data = data;
return this;
}
// 设置JSON数据
json(data) {
this.request.data = JSON.stringify(data);
this.request.headers['Content-Type'] = 'application/json';
return this;
}
// 设置表单数据
form(data) {
const formData = new FormData();
Object.entries(data).forEach(([key, value]) => {
formData.append(key, value);
});
this.request.data = formData;
return this;
}
// 设置超时时间
timeout(ms) {
this.request.timeout = ms;
return this;
}
// 设置重试次数
retry(count) {
this.request.retries = count;
return this;
}
// 启用缓存
cache(enabled = true) {
this.request.cache = enabled;
return this;
}
// 设置认证信息
auth(token, type = 'Bearer') {
this.request.headers['Authorization'] = `${type} ${token}`;
return this;
}
// 设置响应类型
responseType(type) {
this.request.responseType = type;
return this;
}
// 添加请求拦截器
interceptRequest(interceptor) {
this.request.interceptors.request.push(interceptor);
return this;
}
// 添加响应拦截器
interceptResponse(interceptor) {
this.request.interceptors.response.push(interceptor);
return this;
}
// 构建并返回请求对象
build() {
// 验证必要参数
if (!this.request.url) {
throw new Error('URL is required');
}
return this.request;
}
// 构建并立即执行请求
async execute() {
const request = this.build();
return await request.execute();
}
}
// 高级建造者 - 支持预设配置
class AdvancedHttpRequestBuilder extends HttpRequestBuilder {
constructor() {
super();
this.presets = new Map();
this.setupDefaultPresets();
}
setupDefaultPresets() {
// API请求预设
this.presets.set('api', (builder) => {
return builder
.header('Content-Type', 'application/json')
.header('Accept', 'application/json')
.timeout(10000)
.retry(2);
});
// 文件上传预设
this.presets.set('upload', (builder) => {
return builder
.method('POST')
.timeout(30000)
.retry(1);
});
// 快速GET请求预设
this.presets.set('get', (builder) => {
return builder
.method('GET')
.cache(true)
.timeout(5000);
});
// GraphQL请求预设
this.presets.set('graphql', (builder) => {
return builder
.method('POST')
.header('Content-Type', 'application/json')
.timeout(15000);
});
}
// 应用预设配置
preset(name) {
if (!this.presets.has(name)) {
throw new Error(`Unknown preset: ${name}`);
}
const presetFn = this.presets.get(name);
return presetFn(this);
}
// 注册自定义预设
registerPreset(name, presetFn) {
this.presets.set(name, presetFn);
return this;
}
// 条件设置
when(condition, callback) {
if (condition) {
callback(this);
}
return this;
}
// 批量配置
configure(config) {
Object.entries(config).forEach(([key, value]) => {
if (typeof this[key] === 'function') {
this[key](value);
}
});
return this;
}
}
// 使用示例
console.log('=== 建造者模式测试 ===');
// 基础使用
const basicRequest = new HttpRequestBuilder()
.url('https://api.example.com/users')
.method('GET')
.header('Authorization', 'Bearer token123')
.param('page', 1)
.param('limit', 10)
.timeout(8000)
.cache(true)
.build();
console.log('Basic request config:', basicRequest.getConfig());
// 链式调用创建POST请求
const postRequest = new HttpRequestBuilder()
.url('https://api.example.com/users')
.method('POST')
.json({
name: 'John Doe',
email: 'john@example.com',
age: 30
})
.auth('token123')
.retry(3)
.interceptRequest(async (config) => {
console.log('Request interceptor:', config.url);
return config;
})
.interceptResponse(async (response) => {
console.log('Response interceptor:', response.status);
return response;
});
// 执行请求
postRequest.execute().then(response => {
console.log('POST request response:', response);
});
// 高级建造者使用
const advancedBuilder = new AdvancedHttpRequestBuilder();
// 使用预设配置
const apiRequest = advancedBuilder
.url('https://api.example.com/data')
.preset('api')
.param('filter', 'active')
.when(true, (builder) => {
builder.header('X-Custom-Header', 'custom-value');
})
.build();
console.log('API request with preset:', apiRequest.getConfig());
// 注册自定义预设
advancedBuilder.registerPreset('authenticated', (builder) => {
return builder
.auth('user-token')
.header('X-Client-Version', '1.0.0')
.timeout(12000);
});
const authRequest = new AdvancedHttpRequestBuilder()
.url('https://api.example.com/profile')
.preset('authenticated')
.build();
console.log('Authenticated request:', authRequest.getConfig());链式调用是建造者模式的重要特征,通过返回this实现方法链,提供流畅的编程体验。
// 🎉 高级链式调用实现
// SQL查询建造者
class SQLQueryBuilder {
constructor() {
this.reset();
}
reset() {
this.query = {
type: '',
table: '',
fields: [],
joins: [],
conditions: [],
groupBy: [],
having: [],
orderBy: [],
limit: null,
offset: null
};
return this;
}
// SELECT查询
select(...fields) {
this.query.type = 'SELECT';
this.query.fields = fields.length > 0 ? fields : ['*'];
return this;
}
// INSERT查询
insert(data) {
this.query.type = 'INSERT';
this.query.data = data;
return this;
}
// UPDATE查询
update(data) {
this.query.type = 'UPDATE';
this.query.data = data;
return this;
}
// DELETE查询
delete() {
this.query.type = 'DELETE';
return this;
}
// FROM子句
from(table) {
this.query.table = table;
return this;
}
// INTO子句(用于INSERT)
into(table) {
this.query.table = table;
return this;
}
// JOIN子句
join(table, condition, type = 'INNER') {
this.query.joins.push({
type,
table,
condition
});
return this;
}
// LEFT JOIN
leftJoin(table, condition) {
return this.join(table, condition, 'LEFT');
}
// RIGHT JOIN
rightJoin(table, condition) {
return this.join(table, condition, 'RIGHT');
}
// INNER JOIN
innerJoin(table, condition) {
return this.join(table, condition, 'INNER');
}
// WHERE子句
where(condition, operator = 'AND') {
this.query.conditions.push({
condition,
operator: this.query.conditions.length === 0 ? '' : operator
});
return this;
}
// AND WHERE
andWhere(condition) {
return this.where(condition, 'AND');
}
// OR WHERE
orWhere(condition) {
return this.where(condition, 'OR');
}
// WHERE IN
whereIn(field, values) {
const condition = `${field} IN (${values.map(v => `'${v}'`).join(', ')})`;
return this.where(condition);
}
// WHERE BETWEEN
whereBetween(field, min, max) {
const condition = `${field} BETWEEN '${min}' AND '${max}'`;
return this.where(condition);
}
// WHERE LIKE
whereLike(field, pattern) {
const condition = `${field} LIKE '${pattern}'`;
return this.where(condition);
}
// GROUP BY子句
groupBy(...fields) {
this.query.groupBy.push(...fields);
return this;
}
// HAVING子句
having(condition) {
this.query.having.push(condition);
return this;
}
// ORDER BY子句
orderBy(field, direction = 'ASC') {
this.query.orderBy.push({
field,
direction: direction.toUpperCase()
});
return this;
}
// ORDER BY DESC
orderByDesc(field) {
return this.orderBy(field, 'DESC');
}
// LIMIT子句
limit(count) {
this.query.limit = count;
return this;
}
// OFFSET子句
offset(count) {
this.query.offset = count;
return this;
}
// 分页
paginate(page, perPage) {
this.query.limit = perPage;
this.query.offset = (page - 1) * perPage;
return this;
}
// 构建SQL字符串
build() {
let sql = '';
switch (this.query.type) {
case 'SELECT':
sql = this.buildSelect();
break;
case 'INSERT':
sql = this.buildInsert();
break;
case 'UPDATE':
sql = this.buildUpdate();
break;
case 'DELETE':
sql = this.buildDelete();
break;
default:
throw new Error('Query type not specified');
}
return sql.trim();
}
buildSelect() {
let sql = `SELECT ${this.query.fields.join(', ')}`;
if (this.query.table) {
sql += ` FROM ${this.query.table}`;
}
// JOIN子句
this.query.joins.forEach(join => {
sql += ` ${join.type} JOIN ${join.table} ON ${join.condition}`;
});
// WHERE子句
if (this.query.conditions.length > 0) {
sql += ' WHERE ';
sql += this.query.conditions.map(cond =>
`${cond.operator} ${cond.condition}`.trim()
).join(' ');
}
// GROUP BY子句
if (this.query.groupBy.length > 0) {
sql += ` GROUP BY ${this.query.groupBy.join(', ')}`;
}
// HAVING子句
if (this.query.having.length > 0) {
sql += ` HAVING ${this.query.having.join(' AND ')}`;
}
// ORDER BY子句
if (this.query.orderBy.length > 0) {
const orderClauses = this.query.orderBy.map(order =>
`${order.field} ${order.direction}`
);
sql += ` ORDER BY ${orderClauses.join(', ')}`;
}
// LIMIT子句
if (this.query.limit !== null) {
sql += ` LIMIT ${this.query.limit}`;
}
// OFFSET子句
if (this.query.offset !== null) {
sql += ` OFFSET ${this.query.offset}`;
}
return sql;
}
buildInsert() {
if (!this.query.table || !this.query.data) {
throw new Error('Table and data are required for INSERT');
}
const fields = Object.keys(this.query.data);
const values = Object.values(this.query.data).map(v => `'${v}'`);
return `INSERT INTO ${this.query.table} (${fields.join(', ')}) VALUES (${values.join(', ')})`;
}
buildUpdate() {
if (!this.query.table || !this.query.data) {
throw new Error('Table and data are required for UPDATE');
}
const setClauses = Object.entries(this.query.data)
.map(([key, value]) => `${key} = '${value}'`);
let sql = `UPDATE ${this.query.table} SET ${setClauses.join(', ')}`;
// WHERE子句
if (this.query.conditions.length > 0) {
sql += ' WHERE ';
sql += this.query.conditions.map(cond =>
`${cond.operator} ${cond.condition}`.trim()
).join(' ');
}
return sql;
}
buildDelete() {
if (!this.query.table) {
throw new Error('Table is required for DELETE');
}
let sql = `DELETE FROM ${this.query.table}`;
// WHERE子句
if (this.query.conditions.length > 0) {
sql += ' WHERE ';
sql += this.query.conditions.map(cond =>
`${cond.operator} ${cond.condition}`.trim()
).join(' ');
}
return sql;
}
// 执行查询(模拟)
async execute() {
const sql = this.build();
console.log('Executing SQL:', sql);
// 模拟数据库查询
await new Promise(resolve => setTimeout(resolve, 100));
return {
sql,
rows: [
{ id: 1, name: 'John', email: 'john@example.com' },
{ id: 2, name: 'Jane', email: 'jane@example.com' }
],
rowCount: 2
};
}
// 获取查询信息
getQueryInfo() {
return {
type: this.query.type,
table: this.query.table,
complexity: this.calculateComplexity()
};
}
calculateComplexity() {
let complexity = 1;
complexity += this.query.joins.length * 2;
complexity += this.query.conditions.length;
complexity += this.query.groupBy.length;
complexity += this.query.orderBy.length;
return complexity;
}
}
// 表单建造者
class FormBuilder {
constructor() {
this.form = {
fields: [],
validation: {},
layout: 'vertical',
submitButton: { text: 'Submit', style: 'primary' },
resetButton: null
};
}
// 添加文本输入字段
addTextField(name, label, options = {}) {
this.form.fields.push({
type: 'text',
name,
label,
placeholder: options.placeholder || '',
required: options.required || false,
maxLength: options.maxLength,
pattern: options.pattern
});
return this;
}
// 添加邮箱字段
addEmailField(name, label, required = false) {
this.form.fields.push({
type: 'email',
name,
label,
required,
pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$'
});
return this;
}
// 添加密码字段
addPasswordField(name, label, options = {}) {
this.form.fields.push({
type: 'password',
name,
label,
required: options.required || false,
minLength: options.minLength || 6,
showStrength: options.showStrength || false
});
return this;
}
// 添加选择字段
addSelectField(name, label, options, required = false) {
this.form.fields.push({
type: 'select',
name,
label,
options,
required
});
return this;
}
// 添加复选框
addCheckboxField(name, label, checked = false) {
this.form.fields.push({
type: 'checkbox',
name,
label,
checked
});
return this;
}
// 添加单选按钮组
addRadioGroup(name, label, options, required = false) {
this.form.fields.push({
type: 'radio',
name,
label,
options,
required
});
return this;
}
// 添加文本域
addTextArea(name, label, options = {}) {
this.form.fields.push({
type: 'textarea',
name,
label,
rows: options.rows || 4,
maxLength: options.maxLength,
required: options.required || false
});
return this;
}
// 设置表单布局
layout(layout) {
this.form.layout = layout; // 'vertical', 'horizontal', 'inline'
return this;
}
// 设置提交按钮
submitButton(text, style = 'primary') {
this.form.submitButton = { text, style };
return this;
}
// 添加重置按钮
resetButton(text = 'Reset', style = 'secondary') {
this.form.resetButton = { text, style };
return this;
}
// 添加验证规则
addValidation(fieldName, rules) {
this.form.validation[fieldName] = rules;
return this;
}
// 批量添加验证规则
validation(rules) {
Object.assign(this.form.validation, rules);
return this;
}
// 构建表单
build() {
return {
...this.form,
render: this.render.bind(this),
validate: this.validate.bind(this)
};
}
// 渲染表单HTML
render() {
let html = `<form class="form-${this.form.layout}">`;
this.form.fields.forEach(field => {
html += this.renderField(field);
});
html += '<div class="form-buttons">';
html += `<button type="submit" class="btn btn-${this.form.submitButton.style}">${this.form.submitButton.text}</button>`;
if (this.form.resetButton) {
html += `<button type="reset" class="btn btn-${this.form.resetButton.style}">${this.form.resetButton.text}</button>`;
}
html += '</div></form>';
return html;
}
renderField(field) {
let html = `<div class="form-field form-field-${field.type}">`;
html += `<label for="${field.name}">${field.label}${field.required ? ' *' : ''}</label>`;
switch (field.type) {
case 'text':
case 'email':
case 'password':
html += `<input type="${field.type}" id="${field.name}" name="${field.name}"`;
if (field.placeholder) html += ` placeholder="${field.placeholder}"`;
if (field.required) html += ' required';
if (field.maxLength) html += ` maxlength="${field.maxLength}"`;
if (field.pattern) html += ` pattern="${field.pattern}"`;
html += '>';
break;
case 'select':
html += `<select id="${field.name}" name="${field.name}"${field.required ? ' required' : ''}>`;
field.options.forEach(option => {
html += `<option value="${option.value}">${option.label}</option>`;
});
html += '</select>';
break;
case 'textarea':
html += `<textarea id="${field.name}" name="${field.name}" rows="${field.rows}"`;
if (field.required) html += ' required';
if (field.maxLength) html += ` maxlength="${field.maxLength}"`;
html += '></textarea>';
break;
case 'checkbox':
html += `<input type="checkbox" id="${field.name}" name="${field.name}"${field.checked ? ' checked' : ''}>`;
break;
case 'radio':
field.options.forEach((option, index) => {
html += `<input type="radio" id="${field.name}_${index}" name="${field.name}" value="${option.value}">`;
html += `<label for="${field.name}_${index}">${option.label}</label>`;
});
break;
}
html += '</div>';
return html;
}
// 验证表单数据
validate(data) {
const errors = {};
this.form.fields.forEach(field => {
const value = data[field.name];
const rules = this.form.validation[field.name];
// 必填验证
if (field.required && (!value || value.trim() === '')) {
errors[field.name] = `${field.label} is required`;
return;
}
// 自定义验证规则
if (rules && value) {
if (rules.minLength && value.length < rules.minLength) {
errors[field.name] = `${field.label} must be at least ${rules.minLength} characters`;
}
if (rules.maxLength && value.length > rules.maxLength) {
errors[field.name] = `${field.label} must not exceed ${rules.maxLength} characters`;
}
if (rules.pattern && !new RegExp(rules.pattern).test(value)) {
errors[field.name] = `${field.label} format is invalid`;
}
if (rules.custom && typeof rules.custom === 'function') {
const customError = rules.custom(value);
if (customError) {
errors[field.name] = customError;
}
}
}
});
return {
isValid: Object.keys(errors).length === 0,
errors
};
}
}
// 使用示例
console.log('=== 链式调用测试 ===');
// SQL查询建造者使用
const query = new SQLQueryBuilder()
.select('users.name', 'users.email', 'profiles.avatar')
.from('users')
.leftJoin('profiles', 'users.id = profiles.user_id')
.where('users.active = 1')
.andWhere('users.created_at > "2023-01-01"')
.orderBy('users.name')
.limit(10)
.build();
console.log('Generated SQL:', query);
// 复杂查询示例
const complexQuery = new SQLQueryBuilder()
.select('COUNT(*) as total', 'category')
.from('products')
.where('price > 100')
.whereIn('category', ['electronics', 'books', 'clothing'])
.groupBy('category')
.having('COUNT(*) > 5')
.orderByDesc('total')
.build();
console.log('Complex SQL:', complexQuery);
// 表单建造者使用
const registrationForm = new FormBuilder()
.addTextField('username', 'Username', { required: true, maxLength: 50 })
.addEmailField('email', 'Email Address', true)
.addPasswordField('password', 'Password', { required: true, minLength: 8, showStrength: true })
.addSelectField('country', 'Country', [
{ value: 'us', label: 'United States' },
{ value: 'ca', label: 'Canada' },
{ value: 'uk', label: 'United Kingdom' }
], true)
.addCheckboxField('newsletter', 'Subscribe to newsletter')
.addTextArea('bio', 'Biography', { rows: 4, maxLength: 500 })
.layout('vertical')
.submitButton('Create Account', 'success')
.resetButton('Clear Form')
.validation({
username: {
minLength: 3,
pattern: '^[a-zA-Z0-9_]+$',
custom: (value) => {
if (value.toLowerCase().includes('admin')) {
return 'Username cannot contain "admin"';
}
return null;
}
},
password: {
pattern: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d@$!%*?&]{8,}$',
custom: (value) => {
if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
return 'Password must contain at least one uppercase letter, one lowercase letter, and one number';
}
return null;
}
}
})
.build();
console.log('Form HTML:', registrationForm.render());
// 表单验证测试
const formData = {
username: 'john_doe',
email: 'john@example.com',
password: 'Password123',
country: 'us',
newsletter: true,
bio: 'I am a software developer.'
};
const validationResult = registrationForm.validate(formData);
console.log('Form validation:', validationResult);链式调用设计原则:
💼 实际应用:链式调用在现代JavaScript库中广泛应用,如jQuery、Lodash、Moment.js等,提供了优雅的API设计和良好的开发体验。
通过本节JavaScript建造者模式完整指南的学习,你已经掌握:
A: 建造者模式关注复杂对象的分步构建过程,通常使用链式调用;工厂模式关注对象的创建逻辑封装,通常一次性创建对象。建造者模式更适合参数多、配置复杂的场景。
A: 当对象有很多可选参数、需要分步骤构建、或者希望提供流畅的API体验时,应该考虑使用建造者模式。特别适用于配置对象、查询构建器、表单构建等场景。
A: 链式调用本身对性能影响很小,主要开销在于方法调用和对象状态维护。在大多数场景下,这种开销是可以接受的,而且链式调用带来的开发体验提升更有价值。
A: 可以在每个设置方法中进行参数验证,或者在build()方法中进行最终验证。建议采用渐进式验证,既保证数据有效性,又不影响链式调用的流畅性。
A: 建造者模式可以支持异步操作,但需要特殊设计。可以返回Promise对象或者使用async/await语法,但这会打破传统的链式调用模式。
// 问题:如何在建造者模式中支持异步操作
// 解决:使用Promise链或async/await
class AsyncBuilder {
constructor() {
this.config = {};
this.promise = Promise.resolve();
}
setConfig(key, value) {
this.promise = this.promise.then(() => {
this.config[key] = value;
return this;
});
return this;
}
async loadData(url) {
this.promise = this.promise.then(async () => {
const response = await fetch(url);
this.config.data = await response.json();
return this;
});
return this;
}
async build() {
await this.promise;
return this.config;
}
}// 问题:如何在建造者中实现复杂的验证逻辑
// 解决:实现验证器链
class ValidatedBuilder {
constructor() {
this.data = {};
this.validators = [];
}
addValidator(field, validator) {
this.validators.push({ field, validator });
return this;
}
set(field, value) {
// 立即验证
const fieldValidators = this.validators.filter(v => v.field === field);
for (const { validator } of fieldValidators) {
const error = validator(value);
if (error) {
throw new Error(`Validation failed for ${field}: ${error}`);
}
}
this.data[field] = value;
return this;
}
build() {
// 最终验证
this.validators.forEach(({ field, validator }) => {
const value = this.data[field];
const error = validator(value);
if (error) {
throw new Error(`Final validation failed for ${field}: ${error}`);
}
});
return { ...this.data };
}
}"掌握建造者模式,让你的API设计更加优雅和易用。每一个流畅的链式调用,都是对开发体验的提升!"