一个模式就是一个可重用的方案。当代码是建立在行之有效的模式上时,我们可以花更少的时间去关心我们的代码结构,从而能花…
- 引言
- 设计模式分类
- 常见设计模式
- 单例模式
- 观察者模式
- 工厂模式
- 策略模式
- 代理模式
引言
JavaScript 设计模式,一个模式就是一个可重用的方案。当代码是建立在行之有效的模式上时,我们可以花更少的时间去关心我们的代码结构,从而能花更多的时间关注我们的解决方案的整体质量。
设计模式分类
三大类
「创建型模式」 5种
- 单例模式
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 原型模式
「结构型模式」 7种
- 代理模式
- 适配器模式
- 装饰器模式
- 外观模式
- 桥接模式
- 组合模式
- 享元模式
「行为型模式」 11种
- 观察者模式
- 策略模式
- 模板方法模式
- 迭代子模式
- 责任链模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式
常见设计模式
1. 单例模式 Singleton Pattern:
1-1 原理
顾名思义就是保证每个类都只有一个实例对象(调用一个类,任何时候返回的都是同一个实例)
1-2 实现方法
使用一个变量来标志当前是否已经为某个类创建过对象,如果创建了,则在下一次获取该类的实例时, 直接返回之前创建的对象,否则就创建一个对象
1-3 coding
var Universe;
(function () {
var instance;
Universe = function Universe() {
if (instance) {
return instance;
}
instance = this;
// 其它内容
this.start_time = 0;
this.bang = "Big";
};
} ());
//测试代码
var a = new Universe();
var b = new Universe();
alert(a === b); // true
1-4 场景
用于: 一个全局使用的类频繁地创建与销毁
- 要求生产唯一序列号
- WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来
- 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等
2. 发布订阅(观察者模式)
2-1 原理
当对象间存在一对多关系时,则使用观察者模式. 比如,当一个对象被修改时,则会自动通知它的依赖对象
2-2 实现方法
订阅,就是把几个函数推入数组中待用; 发布,就是把缓存在数组中的那一坨函数列队执行
2-3 coding
var event = {
eventList:{},
listen:function(key,fn){
if(!this.eventList[key]){
this.eventList[key] = [];
}
this.eventList[key].push(fn);
},
remove:function(key,fn){
var fns = this.eventList[key];
if(!fns){
return false;
}
if(!fn){
// 如果没有回调,表示取消此key下所有方法
fns && (fns.length=0); // 这是一种快速清空数组的方法哦!
}else{
for(var i=0;i<fns.length;i++){
//遍历方法列表,剔除需要取消的方法
//要注意fns是引用型变量,实际是去除了this.eventList[key]下的方法。
if(fns[i] === fn){
fns.splice(i,1);
}
}
}
},
//trigger('loginSuccess',参数1,参数2)
trigger:function(){
//出列第一个数据:'loginSuccess'
var key = Array.prototype.shift.call(arguments);
var fns = this.eventList[key];//拿到一组函数
if(!fns || fns.length === 0){
//没有要执行的函数,就返回
return false;
}
for(var i=0;i<fns.length;i++){
//arguments已经出列了一个数据,目前全是参数列表了
fns[i].apply(this,arguments);
}
}
};
var installEvent = function(obj){
for(var i in event){
obj[i] = event[i];
}
}
var login = {};
installEvent(login);
//显示头像
function showAvatar(){
console.log('显示用户头像');
}
//显示消息列表
function showMessage(){
console.log('显示消息列表');
}
//订阅
login.listen('loginSuccess',showAvatar);
login.listen('loginSuccess',showMessage);
//发布
login.trigger('loginSuccess');
//取消订阅
login.remove('loginSuccess',showAvatar);
//再次发布
login.trigger('loginSuccess');
2-4 场景
- 按钮上绑定click事件
- ajax解耦
3. 工厂模式
3-1 实现原理
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。 而子类可以重写接口方法以便创建的时候指定自己的对象类型
3-2 分类
- 简单工厂模式
- 工厂方法模式
- 抽象工厂模式
分别是在各自基础上有一定的改进: 简单工厂模式解决了入口不统一的问题; 工厂模式解决了修改地点不统一的问题; 抽象工厂模式解决了子类实现不规范的问题
3-3 coding
function Animal(opts){
var obj = new Object();
obj.name = opts.name;
obj.color = opts.color;
obj.getInfo = function(){
return '名称:'+obj.name +', 颜色:'+ obj.color;
}
return obj;
}
var cat = Animal({name: '波斯猫', color: '白色'});
cat.getInfo();
3-4 场景
简单说:假如我们想在网页面里插入一些元素,而这些元素类型不固定,可能是图片、链接、文本, 根据工厂模式的定义,在工厂模式下,工厂函数只需接受我们要创建的元素的类型,其他的工厂函数帮我们处理
4. 策略模式
4-1 原理
俗话说,条条大路(策略)通罗马(result)。在现实生活中,我们可以采用很多方法实现同一个目标。 比如我们先定个小目标,先挣它一个亿。我们可以根据具体的实际情况(按照对应的策略)来完成这个目标
4-2 coding
// 某公司年终奖计算方式
var Strategies = {
"A":function(salary){
return salary * 5;
},
"B":function(salary){
return salary * 4;
},
"C":function(salary){
return salary * 3;
}
};
var caculateBonus = function(level,salary){
return Strategies[level](salary);
};
console.log(caculateBonus("A",2000));
4-3 场景
- antd 中的message组件有info、success、error
- 表单校验
5. 代理模式
5-1 原理
为其他对象提供一种代理以控制对这个对象的访问
5-2 分类
- 保护代理模式
- 虚拟代理模式
- 缓存代理模式
5-3 coding
var Flower = function(){
this.price = 150
}
var xiaoming = {
sendflower: function(target){
var flower = new Flower()
target.receiveFlower(flower )
}
}
var B = {
receiveFlower: function(flower){
if(flower.price < 100){
console.log("太便宜了,女神表示一脸嫌弃")
return false
}else{
A.receiveFlower(flower)
}
},
}
var A = {
receiveFlower: function(){
console.log("接受了鲜花")
}
}
xiaoming.sendFlower(B);
5-4 场景
- 保护过滤
- 缓存代理 - 一些开销比较大的运算结果提供暂时的存储
- 虚拟代理(一些开销很大的对象,延迟到真正需要它的时候才去创建) - 图片上传
最后, 希望大家早日实现:成为编程高手的伟大梦想!
欢迎交流~
本文版权归原作者曜灵所有!未经允许,严禁转载!对非法转载者, 原作者保留采用法律手段追究的权利!
若需转载,请联系微信公众号:连先生有猫病,可获取作者联系方式!