首页 js设计模式-享元模式
文章
取消

js设计模式-享元模式

享元模式

“享元”,被共享的单元,即复用对象,节省内存,注意前提是享元对象是不可变对象。

用一天的时间,抽空看完一种设计模式,或者两天,还是有收获的,我们需要耐心,这个从长远来说,不算慢的。

个人感觉这个享元模式,初步看上去,大概可以理解为一种写代码的良好习惯,性能优化、去掉冗余,在代码开发时候,要避免影响性能的不良习惯。
简单概括就是 dom 创建加载,变量,缓存,代码重用 等等能节省代码执行开支的地方就去优化,去节省。 在编程语言中共有的的理念即:抽离,封装,继承,多态,享元模式也蕴藏了此理念。

享元模式的基本概念:
享元是一种结构型设计模式,它允许你在消耗少量内存的情况下支持大量对象。 模式通过共享多个对象的部分状态来实现上述功能。换句话来说,享元会将不同对象的相同数据进行缓存以节省内存

用一个简单的例子,我们看一下,找找感觉,这个设计模式 很基础,甚至感觉是一种开发理念。

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
37
38
39
40
41
42
43
44
45
46
47
48
// 未经优化的 tooltip 类
let Tooltip = function (targetElement, text) {
  this.target = targetElement;
  this.text = text;
  this.delayTimeout = null;
  this.delay = 1500;

  // create the HTML
  this.element = document.createElement("div");
  this.element.style.display = "none";
  this.element.style.position = "absolute";
  this.element.className = "tooltip";
  document.getElementsByTagName("body")[0].appendChild(this.element);

  // attach the event
  var that = this;
  addEvent(this.target, "mouseover", function (e) {
    that.startDelay(e);
  });
  addEvent(this.target, "mouseout", function (e) {
    that.hide();
  });
};

Tooltip.prototype = {
  startDelay: function (e) {
    if (this.delayTimeout == null) {
      let that = this;
      let x = e.clientX;
      let y = e.clientY;
      this.delayTimeout = setTimeout(function () {
        this.show();
      }, this.delay);
    }
  },
  show: function (x, y) {
    clearTimeout(this.delayTimeout);
    this.delayTimeout = null;
    this.element.style.left = x + "px";
    this.element.style.top = y + 20 + "px";
    this.element.style.display = "block";
  },
  hide: function () {
    clearTimeout(this.delayTimeout);
    this.delayTimeout = null;
    this.element.style.display = "none";
  }
};

上述的这段代码,意味着,我们每每使用到一个提示,就需要创建一个提示 dom 元素,那一个项目操作下来,多少个都有可能,几百几千个的话,是不是会有点崩溃的,性能会很差,浏览器开销会很大。从良好的开发习惯上来讲,这个肯定要优化的,要把示例抽离,只创建一个 提示 dom,在需要的时候,控制展示不同的内容就好了。所以基础单元,要和数据单元进行分离。

在实际应用中,这个唯一创建的提示 dom 这个逻辑,这个行为,就是享元,共享单元。 而我们需要用的动态数据变量,需要抽离出来单独处理,平常代码开发,我们经常提到的,代码功能独立性,就像积木,就像电子元器件,开发思想的重要性。

下面我们看一下,设计模式-享元模式对上面这段案例的处理:

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// manager
let TooltipManager = (function () {
  let storeInstance = null;
  let Tooltip = function () {
    this.delayTimeout = null;
    this.delay = 1500;

    // create the HTML
    this.element = document.createElement("div");
    this.element.style.display = "none";
    this.element.style.position = "absolute";
    this.element.className = "tooltip";
    document.getElementsByTagName("body")[0].appendChild(this.element);
  };

  Tooltip.prototype = {
    startDelay: function (e) {
      if (this.delayTimeout == null) {
        let that = this;
        let x = e.clientX;
        let y = e.clientY;
        this.delayTimeout = setTimeout(function () {
          this.show(x, y, text);
        }, this.delay);
      }
    },
    show: function (x, y, text) {
      clearTimeout(this.delayTimeout);
      this.delayTimeout = null;
      this.element.innerHTML = text;
      this.element.style.left = x + "px";
      this.element.style.top = y + 20 + "px";
      this.element.style.display = "block";
    },
    hide: function () {
      clearTimeout(this.delayTimeout);
      this.delayTimeout = null;
      this.element.style.display = "none";
    }
  };

  return {
    addTooltip: function (targetElement, text) {
      let tt = this.getTooltip();
      addEvent(targetElement, "mouseover", function (e) {
        tt.startDelay(e, text);
      });
      addEvent(targetElement, "mouseout", function (e) {
        tt.hide();
      });
    },
    getTooltip: function () {
      if (storeInstance == null) {
        storeInstance = new Tooltip();
      }
      return storeInstance;
    }
  };
})();

上面这个Tooltip类和未处理前做一个对比,去进一步了解享元模式。

前端常用的地图框架

vue好用的table组件