代理模式
定义:为一个对象提供一个代用品或者占位符,以便控制它的访问。
当我们不方便直接访问某个对象的时候,或者不满足需求时,可考虑使用一个替身对象来控制该对象的访问。替身对象可对请求预先进行处理,再决定是否转交给本体对象。
模式特点
- 代理对象可预先请求处理,再决定是否转交给本体;
- 代理和本体对外显示接口保持一致性
- 代理对象仅对本体做一次包装
模式细分
- 虚拟代理(将开销大的运算延迟到需要时执行)
- 缓存代理(为开销大的运算结果提供缓存)
- 保护代理(黑白双簧,代理充当黑脸,拦截非分要求)
- 防火墙代理(控制网络资源的方向)
在 JS 中常常会用到的代理模式为 ”虚拟代理“ 和 ”缓存代理“.
适用场景
- 虚拟代理
- 图片预加载(loading 图)
- 合并 HTTP 请求(数据上报汇总)
- 缓存代理:(前提本体是纯函数)
- 缓存异步请求数据
- 缓存较为复杂的运算结果
接下来看两个具体的例子:
虚拟代理
虚拟代理的目的,是将开销大的运算延迟到需要时再执行。
我们来看一个虚拟代理在图片预加载的应用。
// 本体
var myImage = (function () {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
return {
setSrc: function (src) {
imgNode.src = src;
}
};
})();
// 代理
var proxyImage = (function () {
var img = new Image();
img.onload = function () {
// 图片加载完设置真实图片 src
myImage.setSrc(this.src);
};
return {
setSrc: function (src) {
// 预先设置图片 src 为 loading 图
myImage.setSrc('./loading.gif');
img.src = src;
}
};
})();
// 外部调用
proxyImage.setSrc('./product.png');
缓存代理(暂时储存)
缓存代理的目的,是为一些开销大的运算结果提供暂时存储,以便下次调用时,参数与结果不变情况下,从缓存返回结果,而不是重新进行本体运算,减少本体调用次数。
var add = function () {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
};
var proxyAdd = (function () {
var cache = {}; //缓存运算结果的缓存对象
return function () {
var args = Array.prototype.join.call(arguments); //把参数用逗号组成一个字符串作为“键”
if (cache.hasOwnProperty(args)) {
//等价 args in cache
console.log('使用缓存结果');
return cache[args]; //直接使用缓存对象的“值”
}
console.log('计算结果');
return (cache[args] = add.apply(this, arguments)); //使用本体函数计算结果并加入缓存
};
})();
console.log(proxyAdd(1, 2, 3, 4, 5));
console.log(proxyAdd(1, 2, 3, 4, 5));
console.log(proxyAdd(1, 2, 3, 4, 5));
复合模式
复合模式结合两个或者两个以上的模式,组成一个解决方案,解决一再发生的一般性问题
MVC 与复合模式
mvc 框架就是一个典型的复合模式
- 观察者模式:V和C都是M的观察者(Model的状态更新要及时通知V更新视图,或者通知C做相应逻辑处理)
- 策略模式:C是V的“策略”,所以V包含的控制逻辑就是“选择策略”,也就是选择控制器Controller
- 组合模式:V的自身实现应用了组合模式(调用顶层容器的repaint方法,容器内的所有组件都会重绘)
与设计模式相处
定义设计模式
模式是在某情境下,针对某问题的某种解决方案
设计模式分类
1、创建型模式
创建型模式涉及到将对象实例化,这类模式都提供一个方法,将客户从所需要实例化的对象中解耦。
- 工厂方法模式:由子类决定要创建的具体类是哪一个。
- 抽象工厂模式:允许客户创建对象的家族,而无需指定它们的具体类。
- 单件模式(单例模式):确保有且只有一个对象被创建。
- 生成器模式(建造者模式):封装一个复杂对象的创建过程。
- 原型模式:通过复制现有的实例来创建新的实例。
2、行为型模式
行为型模式涉及到类和对象如何交互及分配职责。
- 策略模式:封装可以互换的行为,并使用委托来决定要使用哪一个。
- 观察者模式:让对象能够在状态改变时被通知。
- 命令模式:封装请求成为对象。
- 模板方法模式:由子类决定如何实现一个算法中的步骤。
- 迭代器模式:在对象的集合之中游走,而不暴露集合的实现。
- 状态模式:封装了基于状态的行为,并使用委托在行为之间切换。
- 责任链模式:为某个请求创建一个对象链。
- 解释器模式:将每一个语法规则表示成一个类。
- 中介者模式:封装一系列对象之间的交互。
- 备忘录模式:在对象外部存储对象的某个状态。
- 访问者模式:通过访问数据结构中的每个元素,来对元素进行各种操作。
3、结构型模式
结构型模式涉及到类和对象如何被组合以建立新的结构或新的功能。
- 装饰者模式:包装一个对象,以提供新的行为。
- 适配器模式:封装对象,并提供不同的接口。
- 外观模式:简化一群类的接口。
- 组合模式:客户用一致的方式处理对象集合和单个对象。
- 代理模式:包装对象,以控制对此对象的访问。
- 桥接模式:分离抽象与实现,使它们可以独立变化。
- 蝇量模式(享元模式):运用共享技术,减少对象的创建。