zoukankan      html  css  js  c++  java
  • 《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实例。大大减少了对象数量,节省了内存空间。
  • 相关阅读:
    程序员:不要自称为码农
    SpringBoot对静态资源配置
    LeetCode 572. Subtree of Another Tree(子树)
    LeetCode 437. Path Sum III(统计路径和等于sum的路径数量)
    LeetCode 112. Path Sum(判断路径和是否等于一个数)
    LeetCode 617. Merge Two Binary Trees(归并两棵二叉树)
    LeetCode 226. Invert Binary Tree(翻转二叉树)
    Failure to transfer org.apache.maven.plugins:maven-resources-plugin:pom:2.6 的解决办法
    linux-查询某软件的安装的目录
    WebService概念解释
  • 原文地址:https://www.cnblogs.com/followflows/p/1706366.html
Copyright © 2011-2022 走看看