设计模式--代理模式
和平时开发中是用的webpack 代码请求解决跨域问题类似
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
例子;
图片代理:一个很常见的代理模式的应用实例就是对大图浏览的控制。
用户通过浏览器访问网页时先不加载真实的大图,而是通过代理对象的方法来进行处理,在代理对象的方法中,先使用一个线程向客户端浏览器加载一个小图片,然后在后台使用另一个线程来调用大图片的加载方法将大图片加载到客户端。当需要浏览大图片时,再将大图片在新网页中显示。如果用户在浏览大图时加载工作还没有完成,可以再启动一个线程来显示相应的提示信息。通过代理技术结合多线程编程将真实图片的加载放到后台来操作,不影响前台图片的浏览。
使用场景:按职责来划分,通常有以下使用场景: 1、远程代理。 2、虚拟代理。 3、Copy-on-Write 代理。 4、保护(Protect or Access)代理。 5、Cache代理。 6、防火墙(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。
public interface Image {
void display();
}
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
public class ProxyImage implements Image{
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() {
if(realImage == null){
realImage = new RealImage(fileName);
}
realImage.display();
}
}
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 图像将从磁盘加载
image.display();
System.out.println("");
// 图像不需要从磁盘加载
image.display();
}
}
图片第一次冲真是服务获取,第二次就从代理这里获取。代理,相当于劫持了 真是subject,和client 之间的直接关系。
ES6所提供Proxy
构造函数能够让我们轻松的使用代理模式:
var proxy = new Proxy(target, handler);
Proxy
构造函数传入两个参数,第一个参数target
表示所要代理的对象,第二个参数handler
也是一个对象用来设置对所代理的对象的行为。如果想知道Proxy
的具体使用方法,可参考阮一峰的《 ECMAScript入门 - Proxy 》。
图片懒加载
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() {
//真实图片加载完成后,才显示出来 myImage.setSrc(this.src) } return { setSrc: function(src) { console.log('src', src)
// 先使用占位符临时显示 myImage.setSrc('http://seopic.699pic.com/photo/40007/8839.jpg_wh1200.jpg'); img.src = src; } } })(); proxyImage.setSrc('http://seopic.699pic.com/photo/40006/7735.jpg_wh1200.jpg')
缓存代理
平时使用的缓存函数,和装饰器模式有点类似,注意区别
注意事项:
1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。