享元模式

2022/4/9 设计模式 大约 2 分钟

目的是减少对象/代码数量,运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类的开销,从而提高系统资源的利用率。

享元模式的主要优点是:

  • 相同对象只要保存一份,降低了系统中对象的数量。
  • 降低了系统中细粒度对象给内存带来的压力。

享元模式的主要缺点是:

  • 为了使对象可以共享,需要将一些不能共享的状态外部化,这将增加程序的复杂性。
  • 读取享元模式的外部状态会使得运行时间稍微变长。

# 示例一

有一百种不同文字的弹窗,每种弹窗行为相同,但是文字和样式不同,我们没必要新建一百个弹窗对象

function Pop() {};

// 保留同样的行为
Pop.prototype.action = function () {};

// 显示弹窗
Pop.prototype.show = function () {};

// 提取出每个弹窗会不同的部分作为一个外部数组
var popArr = [
    {text: 'this is window1', style: [400, 400]},
    {text: 'this is window2', style: [300, 300]},
]
var poper = new Pop();
for (var i = 0; i < 100; i++) {
    poper.show(popArr[i]);
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

1、只需要一个类,不需要new一百次弹窗。 2、这个类只保留所有弹窗共有的,每个弹窗不同的部分留作为一个公共享元。

# 示例二

项目中有一个文件上传功能,该功能可以上传多个文件。

优化前

function uploader(fileType, file) {
    this.fileTye = fileType;
    this.file = file;
}

uploader.prototype.init = function (){/*初始化文件上传的html*/}

uploader.prototype.delete = function (){/*删除掉html*/}

uploader.prototype.uploading = function (){/*上传*/}

var file1, file2, file3

new uploader('img', file1);
new uploader('txt', file2);
new uploader('word', file3);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

未优化之前,我们上传多个不同类型的文件时,就需要new多个uploader的实例对象。

优化后

function uploader(fileType, file) {
    this.fileTye = fileType;
    this.file = file;
}

uploader.prototype.init = function (){/*初始化文件上传的html*/}

uploader.prototype.delete = function (){/*删除掉html*/}

uploader.prototype.uploading = function (){/*上传*/}

var file1, file2, file3

var data = [
    {
        type: 'img',
        file: file1,
    },
    {
        type: 'word',
        file: file2
    }
]

var uploader = new uploader('img', file1);

for (var i = 0; i < data.length; i++) {
    uploader.uploading( data[i].type, data[i].file );
}
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

优化后我们把公共的方法(init、delete、uploading)作为享元,然后只需要循环我们的文件列表就行了

# 示例三

jquery中的extends方法,可以判断参数数量进行不同的操作。

优化前

function extend () {
    if (arguments.length === 1) {
        for (var item in arguments[0]) {
            this[item] = arguments[0][item]
        }
    } else {
        for (var item in arguments[1]) {
            arguments[0][item] = arguments[1][item]
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11

优化后

function extend () {
    var target = arguments[0];
    var source;
    
    if (arguments.length === 1) {
        target = this;
        source = arguments[0];
    } else {
        target = arguments[0];
        source = arguments[1];
    }
    
    for (var item in source) {
        target[item] = source[item]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
上次编辑于: 2023年7月4日 09:36