Iwen's blog Iwen's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于

Iwen

不摸鱼的哥哥
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于
  • Vue

  • Vue进阶

  • CSS

  • ES6

  • Base

  • Core

  • Array

  • Object

  • String

  • Async

  • Browser

  • Http

  • 性能优化

  • 正则

  • 经典总结

  • 设计模式

    • 单例模式
    • 策略模式
    • 观察者模式
    • 代理模式
      • 送花的例子
      • 图片懒加载
      • ES6的Proxy
    • 职责链模式
  • 数据结构

  • 算法

  • 手写

  • TypeScript

  • 复盘
  • 设计模式
Mr.w
2020-11-29

代理模式

# 代理模式

为一个对象提供一个代用品或占位符,以便控制对它的访问。

代理模式确实很方便,通常如果面临一些很大开销的操作,就可以并采用虚拟代理的方式延迟到需要它的时候再去创建,比如懒加载操作。

在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用。代理可以帮客户过滤掉一些请求并且把一些开销大的对象,延迟到真正需要它时才创建。

在 JS 中比较典型的代理有图片懒加载,合并 http 请求,以及缓存计算乘积。

# 送花的例子

class Flower {
    constructor(name) {
        this.name = name;
    }
}

// 送花人 小明
let xiaoming = {
    name: '小明',
    sendFlower(target) {
        target.receiveFlower(this.name)
    }
}
// 代理B
let B = {
    receiveFlower(customer) {
        // 当然要等小红好心情时才送花,也在送花时,才创建花
        A.listenGoodMood(() => {
            A.receiveFlower(new Flower(customer + '的花'))
        })
    } 
}
// 心仪对象 小红
let A = {
    name: '小红',
    receiveFlower(flower) {
        console.log(this.name + '收到:' + flower.name)
    },
    listenGoodMood(fn) {
        setTimeout(() => {
            fn()
        }, 1000)
    }
}

xiaoming.sendFlower(B) // 小红收到:小明的花
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

# 图片懒加载

下面是一个图片懒加载的例子,我们加先加载默认图片,等真实图片加载完之后再替换默认图片。

const createImage = (function() {
    const img = document.createElement('img');
    document.body.appendChild(img);

    return function(src) {
        img.src = src;
    }
})();

const proxyImage = function(fn) {
    const image = new Image();
    const defaultImg = 'https://rs.vip.miui.com/vip-resource/prod/mio/v136/static/media/lazyLoad.a10ffbd7.png';

    return function(src) {
        fn(defaultImg);

        // 这里加一个延迟,可以更好的看到图片替换的过程。
        setTimeout(function() {
            image.src = src;
            image.onload = function() {
                fn(src);
            };
        }, 2000);
    };
};

const proxy = proxyImage(createImage);
proxy('https://pic1.zhimg.com/80/v2-ec33fcec249a9cabab61b14436432bf0_r.jpg');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# ES6的Proxy

Proxy 是 ES6 提供的专门以代理角色出现的代理器,Vue 3.0 的响应式数据部分弃用了 Object.defineProperty,使用 Proxy 来代替它。

现在用Proxy模拟一下另一种场景:

为了保护不及格的同学,课代表拿到全班成绩单后只会公示及格人的成绩。对考分有疑问的考生,复议后新分数比以前大10分才有权利去更新成绩

const list = {
    'A': 100,
    'B': 70,
    'C': 50
}

const obj = new Proxy(list, {
    get(target, key) {
        if(target[key] > 60) {
            console.log('考试及格')
            return target[key]
        } else {
            console.log('不及格的成绩无法公示')
        }
    },
    set(target, key, newVal) {
        if(newVal - target[key] > 10) {
            target[key] = newVal
            console.log('修改成绩:success')
        } else {
            console.log('修改成绩:error')
        }
    }
})

obj.A;          // 考试及格
obj.B;          // 考试及格
obj.C;          // 不及格的成绩无法公示

obj.A = 111;    // success
obj.B = 20;     // error
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
观察者模式
职责链模式

← 观察者模式 职责链模式→

最近更新
01
flex布局页面自适应滚动条问题
12-28
02
前后端分离开发请求接口跨域如何携带cookie的问题
12-28
03
怎么实现div长宽比固定width-height4比3
12-28
更多文章>
Theme by Vdoing | Copyright © 2017-2022 Iwen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式