• 《JavaScript设计模式》读书笔记:Flyweight模式


    Flyweight模式是一种结构型设计模式,它主要解决的问题是:由于(同类)对象的数量太大,采用面向对象技术时给系统带来了难以承受的内存开销。

    拿前端页面常用的tooltip来说。

    未使用享元模式的代码

    var Tooltip = function(targetElement, text) {
      this.target = targetElement;
      this.text = text;
      this.delayTimeout = null;
      this.delay = 1500; // in milliseconds.
    
      // 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);
      this.element.innerHTML = this.text;
      // Attach the events.
    
      var that = this; // Correcting the scope.
    
      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) {
          var that = this;
          var x = e.clientX;
          var y = e.clientY;
          this.delayTimeout = setTimeout(function() { 
            that.show(x, y); 
          }, 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';
      }
    };

    这是Tooltip类的定义。在前端这样使用:

    var linkElement = $('link-id');
    var tt = new Tooltip(linkElement, 'Lorem ipsum...');
    这样使用有一个很大的弊端就是:在前端页面上,可能有许许多多成百上千的元素需要用到tooltip。
    如果为这些元素每个都生成一个Tooltip对象,那将极大的浪费内存,效率也非常低下。
    这时就可以使用享元模式来改造这个类,代码如下:
    /* Tooltip class, as a flyweight. */
    
    var Tooltip = function() {
      this.delayTimeout = null;
      this.delay = 1500; // in milliseconds.
    
      // 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, text) {
        if(this.delayTimeout == null) {
          var that = this;
          var x = e.clientX;
          var y = e.clientY;
          this.delayTimeout = setTimeout(function() { 
            that.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';
      }
    };
    /* TooltipManager singleton, a flyweight factory and manager. */
    
    var TooltipManager = (function() {
      var storedInstance = null;
      
      /* Tooltip class, as a flyweight. */
    
      var Tooltip = function() {
        ...
      };
     Tooltip.prototype = {
       ...
      };
      return {
        addTooltip: function(targetElement, text) {
          // Get the tooltip object.
    
          var tt = this.getTooltip();
          
          // Attach the events.
    
          addEvent(targetElement, 'mouseover', function(e) { tt.startDelay(e, text); });
          addEvent(targetElement, 'mouseout', function(e) { tt.hide(); });      
        },
        getTooltip: function() {
          if(storedInstance == null) {
            storedInstance = new Tooltip();
          }
          return storedInstance;
        }
      };
    })();
    改造后的Tooltip类在前段这样使用:
    TooltipManager.addTooltip($('link-id'), 'Lorem ipsum...');
     
    用享用模式改造后的类相比以前的类有了一些改进。
    它创建了一个闭包,将Tooltip类和集Tooltip对象管理和Tooltip工厂方法于一体的TooltipManager类放置其中,并返回一个singleton。
    将tooltip的触发元素targetElement和文本text从Tooltip类的构造函数中取出,并将它们作为参数传入sinleton里的addTooltip方法中。
    在使用这个新的Tooltip类时,我们只需要用TooltipManager类中的addTooltip方法即可。
    TooltipManager中的getTooltip方法保证了全局中只有一个Tooltip实例。大大减少了对象数量,节省了内存空间。
  • 相关阅读:
    cropper.js 实现裁剪图片并上传头像
    LINQ查询表达式
    c#扩展方法
    lambda表达式
    axios 封装
    Photoshop的混合模式中的叠加实现光照射在背景上的问题
    laravel官方教程-heroku中数据库迁移出现22023的问题
    laravel官方教程-服务器多php指定问题
    浏览器network信息
    理解CommonJs(用于nodejs)、AMD、CMD、ES6模块
  • 原文地址:https://www.cnblogs.com/followflows/p/1706366.html
Copyright © 2020-2023  润新知