AI 时代前端开发最实用的 5 种设计模式
时间:2026-5-15 00:40 作者:独元殇 分类: 前端技术
工作里(主要是前端)会真正有比较重要的实用价值的,我觉得,是这 5 种设计模式。
单例模式、策略模式、装饰器模式、观察者模式、工厂模式。这些内容也是参考 kyriewen 大佬的解析。
这些模式,在 AI 时代用的会比较多,你不跟 AI 讲,它默认会给你效率低的前端代码。我喜欢在合适的场景,让 AI 直接使用这些模式来写我的业务逻辑代码。
如果你是工作需要的话,今天我来简单的说下这是怎么回事。
这些模式主要还是为了防止代码耦合复杂,变成烂面条。
我只是从前端的领域来说说,这些都这么用,是怎么一回事。
单例模式
核心,我们要注意,就是指的业务上只允许有一个控制中心!
就像登录框、登录面板、全局状态 Store、线程池、连接池 这种,这些对象在应用里并不适合反复创建,整个系统用同一个就够了。
其实吧,在前端开发里,单例模式不一定非要写成传统设计模式的样子。很多时候,一个模块、一个闭包、一个默认导出的对象,就跟单例的精髓差不多了。
// 比如 dialog.js
let dialogInstance;
export function getDialog() {
if (!dialogInstance) {
dialogInstance = new Dialog();
}
return dialogInstance;
}
// 甚至下面这样也是
export default {
show() {
// 展示弹窗
},
hide() {
// 关闭弹窗
}
};
没错,ES6 本身就是单例!
来一个完整的例子:
class AppSingleton {
constructor() {
if (!AppSingleton.current) {
this.list = [];
AppSingleton.current = this;
}
return AppSingleton.current;
}
add(value) {
this.list.push(value);
}
}
const first = new AppSingleton();
const second = new AppSingleton();
console.log(first === second); // true
你看,first 和 second 是一样的。
单例模式说白了,就是给“全局公共设施”加一道保险,避免重复创建导致资源浪费和状态混乱。
策略模式
它的主要目的是改善下面这种问题:
if (level === 'normal') {
// 普通会员
} else if (level === 'gold') {
// 黄金会员
} else if (level === 'diamond') {
// 钻石会员
}
一大堆一大堆的 if else 。
维护会困难,而且容易生 bug 。
策略模式,就是吧策略提取出来,比如:
// 不同会员等级对应不同的计价策略
const priceRules = {
normal: (amount) => amount * 0.9,
gold: (amount) => amount * 0.8,
diamond: (amount) => amount * 0.7,
};
// 根据会员等级选择对应策略
function calcMemberPrice(level, amount) {
const rule = priceRules[level];
return rule ? rule(amount) : amount;
}
const price = calcMemberPrice('gold', 100);
console.log(price); // 80
这样,尽可能的避免了 if 和 else 的出现,直接对应不同的函数。
这只是 3 个,但其实如果是十个二十个,谁更好用,不言而明!而且更好维护、替换、复用。
适合处理折扣、校验、排序、支付方式、导出格式这类分支很多但结构相似的逻辑。
装饰器模式
痛点场景是这样的:
有些功能并不属于业务本身,但又经常需要加到函数执行前后,比如日志记录、耗时统计、权限判断、结果缓存等。
还有各种我们的 console 对吧,哈哈。
那,直接硬写我们里面,会让代码混乱。
于是有人想到个办法:原来函数是什么,还是什么,在外面包一层新函数,然后把这些乱七八糟的能力、东西给加进去。
比如 sum ,是你的原函数,就这样用:
// 给函数增加调用日志,但不修改原函数本身
function addLog(fn) {
return function (...args) {
console.log(`正在执行 ${fn.name},参数是:`, args);
const value = fn.apply(this, args);
console.log(`执行结果是:`, value);
return value;
};
}
// 原始业务函数只负责自己的计算逻辑
function sum(a, b) {
return a + b;
}
const sumWithLog = addLog(sum);
sumWithLog(2, 3); // 打印日志,并返回 5
妙吧!!!!
我当年看到这个写法,也虎躯一震赞叹。
sum 和加个壳的 sumWithLog ,真的.... 妙极了!
其实还可以无限套碗,再 with 一大堆东西。我就不举例了。
观察者模式
痛点是啥?
比如购物车的商品数量一变。一大堆的模块,可能都要重新计算、刷新、记录.... 忙死了。
如果是以前那样硬拼,会发现,以后还想加个库存、推荐等等模块,还得去 购物车 那边改代码。
于是有人发明了 观察者模式!
精髓就是【发生变化的模块只负责发出通知,谁关心这个变化,谁自己去订阅。】
比如:
class MessageCenter {
constructor() {
this.listeners = {};
}
// 订阅某个事件
subscribe(type, handler) {
if (!this.listeners[type]) {
this.listeners[type] = [];
}
this.listeners[type].push(handler);
}
// 发布某个事件
publish(type, payload) {
const handlers = this.listeners[type];
if (!handlers) return;
handlers.forEach((handler) => {
handler(payload);
});
}
// 取消订阅
unsubscribe(type, handler) {
const handlers = this.listeners[type];
if (!handlers) return;
this.listeners[type] = handlers.filter((item) => item !== handler);
}
}
const messageCenter = new MessageCenter();
// -------------
// 购物车数量发生变化后,发出一个通知
messageCenter.publish('cart:change', {
count: 3,
total: 299,
});
// -------------
// 导航栏关心购物车数量
messageCenter.subscribe('cart:change', (cart) => {
updateCartBadge(cart.count);
});
// 价格模块关心总金额
messageCenter.subscribe('cart:change', (cart) => {
updateTotalPrice(cart.total);
});
是不是很熟悉,其实Vue 的响应式更新、React 的事件机制、Node.js 里的 EventEmitter 都有用到这种思想。
工厂模式
创建对象,很多时候不是 new 一下就 OK 。
不过说实话,我不是很喜欢在 前端 代码里用 class 这种类。
太累了。。。
我举个 function 的例子:
// 根据角色创建不同用户对象
function buildUser(role) {
const commonInfo = {
createdAt: Date.now(),
};
if (role === 'admin') {
return {
...commonInfo,
role,
permissions: ['read', 'write', 'delete'],
};
}
return {
...commonInfo,
role,
permissions: ['read'],
};
}
// 若你要建立,直接在 role 参数写就 OK 了
const admin = buildUser('admin');
const guest = buildUser('guest');
后面的 'admin' 和 'guest' 就是 工厂模式 的精髓!
就和跟 电子厂、机械厂 老板打交道一样,给一个直接约定好的货,老板就给你开始生产了。复杂度隔离。
参考资料: