一、工厂模式
定义:类似工厂批量生产相同规格的产品,解决对象重复创建问题。
核心:通过函数封装对象的创建过程,调用时无需使用new。
优点:减少重复代码,简化对象创建流程
缺点:无法识别对象的具体类型
function CreatePerson(name, age, sex) {
var obj = {};
obj.name = name;
obj.age = age;
obj.sex = sex;
obj.sayName = function () {
return this.name;
};
return obj;
}
var p1 = CreatePerson("张三", 20, "男");
二、单体模式
定义:确保一个类只有一个实例,并提供全局访问点。
核心:通过变量标识实例是否已创建,已创建则直接返回。
优点:
- 划分命名空间,减少全局变量
- 实例只创建一次,保证一致性
缺点:
- 扩展性差,增加新属性需要修改原代码
- 职责过重,违反单一职责原则
var Singleton = (function () {
var instance = null;
function CreateSingleton(name) {
this.name = name;
}
return function (name) {
if (!instance) {
instance = new CreateSingleton(name);
}
return instance;
};
})();
应用场景:弹窗、缓存、登录窗口等只需一个实例的场景
三、模块模式
定义:为单体模式添加私有变量和私有方法,减少全局污染。
核心:利用闭包封装私有成员,返回公有接口访问。
适用场景:需要初始化数据并公开访问方法的场景
var singleMode = (function () {
var privateNum = 112; // 私有变量
function privateFunc() {} // 私有方法
return {
publicMethod1: function () {},
publicMethod2: function () {},
};
})();
增强模块模式:实例化特定类型并扩展其属性方法
四、代理模式
定义:为一个对象提供一个替身,控制对本体对象的访问。
核心:代理对象与本体对象实现同一接口,将调用传递给本体。
优点:
- 控制本体对象的访问时机
- 推迟本体对象实例化(延迟加载)
var RealImage = function (fileName) {
this.fileName = fileName;
this.loadFromDisk = function () {
console.log("加载文件: " + this.fileName);
};
};
RealImage.prototype.display = function () {
console.log("显示图片: " + this.fileName);
};
var ProxyImage = function (fileName) {
this.realImage = null;
this.fileName = fileName;
};
ProxyImage.prototype.display = function () {
if (!this.realImage) {
this.realImage = new RealImage(this.fileName);
this.realImage.loadFromDisk();
}
this.realImage.display();
};
var img = new ProxyImage("test_10mb.jpg");
img.display();
img.display();
应用场景:图片预加载、合并HTTP请求、延迟加载
五、职责链模式
定义:将请求的发送者和接收者解耦,使多个对象都有机会处理请求。
核心:每个接收者都包含下一个接收者的引用,形成一条链。
优点:
- 降低耦合度,发送者和接收者解耦
- 可以动态调整链的顺序或增删节点
缺点:
- 不保证被处理,请求可能无人处理
- 可能创建多个对象,影响性能
function order500(orderType, pay) {
if (orderType === 1 && pay === true) {
console.log("500元定金,预购成功");
} else {
return "nextSuccessor"; // 传递给下一个
}
}
function order200(orderType, pay) {
if (orderType === 2 && pay === true) {
console.log("200元定金,预购成功");
} else {
return "nextSuccessor";
}
}
应用场景:表单验证、事件处理、权限控制
六、命令模式
定义:将请求封装为命令对象,参数化调用者操作。
核心:命令对象包含execute()方法,调用者只关心命令的执行。
优点:解耦请求发起者与执行者、支持撤销/重做
缺点:
- 命令类数量可能过多,增加系统复杂度
- 命令执行过程无法直观看到
var RefreshMenuBarCommand = function (receiver) {
this.receiver = receiver;
};
RefreshMenuBarCommand.prototype.execute = function () {
this.receiver.refresh();
};
var setCommand = function (button, command) {
button.onclick = function () {
command.execute();
};
};
setCommand(b1, new RefreshMenuBarCommand(MenuBar));
宏命令:一组命令的集合,一次执行多个命令
七、模板方法模式
定义:定义算法骨架,将某些步骤延迟到子类中实现。
核心:父类定义算法框架(模板),子类实现具体步骤。
优点:代码复用、扩展性强、符合开闭原则
缺点:
- 类数目增加,系统复杂度增加
- 继承本身会破坏封装性
var Interview = function () {};
Interview.prototype.writtenTest = function () {};
Interview.prototype.technicalInterview = function () {};
Interview.prototype.leader = function () {};
Interview.prototype.waitNotice = function () {};
Interview.prototype.init = function () {
this.writtenTest();
this.technicalInterview();
this.leader();
this.waitNotice();
};
var BaiDuInterview = function () {};
BaiDuInterview.prototype = new Interview();
BaiDuInterview.prototype.writtenTest = function () {
console.log("百度笔试题目");
};
应用场景:框架搭建、算法框架、组件继承
八、策略模式
定义:定义一系列算法,将每个算法封装起来,使它们可以互换。
核心:策略对象负责算法实现,上下文负责委托执行。
优点:
- 消除大量if-else语句
- 符合开闭原则
- 算法可复用
缺点:
- 策略类数量可能过多
- 必须了解所有策略的区别
var strategies = {
A: function (salary) {
return salary * 4;
},
B: function (salary) {
return salary * 3;
},
C: function (salary) {
return salary * 2;
},
};
var calculateBouns = function (level, salary) {
return strategies[level](salary);
};
应用场景:表单验证、动画缓动、促销活动计算
九、发布订阅模式
定义:定义对象间一对多的依赖关系,当对象状态变化时,所有依赖者收到通知。
核心:发布者不直接通知订阅者,通过消息代理中间层转发。
优点:
- 实现松耦合,发布者和订阅者不直接关联
- 支持广播通信
缺点:
- 订阅者无法知道消息何时被处理
- 可能导致订阅者数量过多
三要素:发布者、订阅者、消息代理
var Event = (function () {
var list = {};
return {
listen: function (key, fn) {
list[key] = list[key] || [];
list[key].push(fn);
},
trigger: function () {
var key = Array.prototype.shift.call(arguments);
var fns = list[key];
if (!fns) return;
for (var i = 0; i < fns.length; i++) {
var fn = fns[i];
fn.apply(this, arguments);
}
},
remove: function (key, fn) {},
};
})();
Event.listen("color", function (size) {
console.log("尺码:" + size);
});
Event.trigger("color", 42);
应用场景:组件通信、模块间通信、异步编程、状态管理
十、中介者模式
定义:用一个中介对象封装一系列对象交互,使对象间耦合松散。
核心:所有对象只与中介者通信,中介者负责协调处理。
优点:解除对象间耦合,便于维护和扩展
缺点:
- 中介者可能变得过于复杂,成为系统瓶颈
- 过度集中管理可能导致中介者职责不清
var Player = function (name, teamColor) {
this.name = name;
this.teamColor = teamColor;
this.state = "alive";
};
Player.prototype.win = function () {
console.log(this.name + " 胜利");
};
Player.prototype.lose = function () {
console.log(this.name + " 失败");
};
Player.prototype.die = function () {
this.state = "dead";
playerDirector.receiveMessage("playerDead", this);
};
var playerDirector = (function () {
var players = {};
var operations = {};
operations.addPlayer = function (player) {
var teamColor = player.teamColor;
players[teamColor] = players[teamColor] || [];
players[teamColor].push(player);
};
operations.playerDead = function (player) {
var teamColor = player.teamColor;
var teamPlayers = players[teamColor];
var allDead = true;
for (var i = 0; i < teamPlayers.length; i++) {
if (teamPlayers[i].state !== "dead") {
allDead = false;
break;
}
}
if (allDead) {
for (var i = 0; i < teamPlayers.length; i++) {
teamPlayers[i].lose();
}
for (var color in players) {
if (color !== teamColor) {
var otherTeam = players[color];
for (var j = 0; j < otherTeam.length; j++) {
otherTeam[j].win();
}
}
}
}
};
return {
addPlayer: function (player) {
operations.addPlayer(player);
},
receiveMessage: function (message, player) {
operations[message](player);
},
};
})();
var player1 = new Player("玩家A", "红队");
var player2 = new Player("玩家B", "红队");
playerDirector.addPlayer(player1);
playerDirector.addPlayer(player2);
应用场景:游戏玩家管理、表单联动、购物车逻辑
十一、JavaScript 设计模式对比总结
| 模式 | 核心问题 | 关键词 |
|---|---|---|
| 工厂模式 | 对象创建 | new、批量生产 |
| 单体模式 | 实例唯一 | 全局唯一 |
| 模块模式 | 封装私有 | 闭包、暴露接口 |
| 代理模式 | 访问控制 | 替身、延迟加载 |
| 职责链模式 | 请求传递 | 链式处理 |
| 命令模式 | 请求封装 | execute()、撤销 |
| 模板方法模式 | 算法骨架 | 继承、框架 |
| 策略模式 | 算法封装 | 互换、委托 |
| 发布订阅模式 | 消息通信 | 订阅、发布、Broker |
| 中介者模式 | 对象协调 | 中心化、解耦 |