javascript 设计模式之享元模式原理与应用详解

本文实例讲述了javascript 设计模式之享元模式。分享给大家供大家参考,具体如下:

享元模式说明

定义:用于解决一个系统大量细粒度对象的共享问题:

关健词:分离跟共享;

说明: 享元模式分单纯(共享)享元模式,以及组合(不共享)享元模式,有共享跟不共享之分;单纯享元模式,只包含共享的状态,可共享状态是不可变,不可修改的,这是享元的内部状态;当然有外部状态就有外部状态,外部状态是可变的,不被共享,这个外部状态由客户端来管理,是可变化的;外部状态与内部状态是独立分开的,外部状态一般作为参数传入享元对象内,但不会影响内部状态的值;外部状态,一用用于获取共享的享元对象,或多或少与内部状态有点关联;比如从用户数据表中获取数据,传入一个外部变量用户名,再根据这个用户名,获取该用户所有对象状态信息;

组合享元模式,配置组合模式来使用,共享部分只做个叶子节点,而组合部分是不必共享的,因为共组部分的子叶节点元素已经被缓存,组合部分相当一个分组分类的作用;

享元模式一般会与工厂模式相结合使用,用于管理缓存的创建跟维护,享元共享元素的创建一般在工厂类里创建;

享元模式主要用于对象的共享,使具有相似对象,或对象间具有太多相似细粒度的状态,能共享已经创建的对象,减少对象的创建,减少对内存的占用,提升优化性能;

一种场景:

享元模式结构图:

像第一张的情况,就可以使用享元模式,因为后两排的状态组合,可能在实体对应中,多次存在,这时就可以使用享元的共享特性,来减少对象的创建,如有相同的状态或组合,就可以获取缓存的状态,减少对象重复创建,减少内存占用;

实例场景:

1>. 系统各种角色权限分配;

2>. 系统出现很多种状态,或组合状态需要对应的,而且这种对应,可以发生很多种其他类型对象上面的,就可以使用享元模式;

实例源码: 单纯(共享)享元

1. 自定义的 JavaScript Hashtable:

function Hashtable() {
  this.values = [];
}

Hashtable.prototype.getJson = function() {
  return this.values;
}

Hashtable.prototype.add = function(key, value) {
  if (!this.contain(key)) {
    this.values.push({key:key, value:value});
  }
}

Hashtable.prototype.contain = function(key) {
  for (idx in this.values) {
    var json = this.values[idx];
    if (json.key == key) {
      return true;
    }
  }
  return false;
}

Hashtable.prototype.get = function(key) {
  var result;
  for (idx in this.values) {
    var json = this.values[idx];
    if (json.key == key) {
      result = json;
      break;
    }
  }
  return result;
}

Hashtable.prototype.delete = function(key) {
  for (idx in this.values) {
    var json = this.values[idx];
    if (json.key == key) {
      delete this.values[idx];
      break;
    }
  }
}

Hashtable.prototype.set = function(key, value) {
  if (this.contain(key)) {
    this.delete(key);
    this.values.push({key:key,value:value});
  }
}

2. 享元方法:

function Flyweight(one) {
  this.stateOne = one;
}

Flyweight.prototype.operate = function(){
   var date = new Date();
  console.log(this.stateOne + '-' + Math.random());
};

这里可以处理传进来的参数的一些逻辑,也可以初始化从数据库里提取数据缓存保存;

3. 享元工厂:

function FlyweightFactory(){
  var hash = new Hashtable();
}

FlyweightFactory.prototype.getFlyweight = function(state) {
  var flyweight;
  if (hash.contain(state)) {
    flyweight = hash.get(state);
  } else {
    flyweight = new Flyweight(state);
    hash.add(state, flyweight);
  }
  return flyweight;
}

4. Client 使用:

//Client

var factory = new FlyweightFactory();
var fly1, fly2, fly3;

fly1 = factory.getFlyweight('AABB');
fly2 = factory.getFlyweight('CCDD');
fly3 = factory.getFlyweight('CCDD');

fly1.operate();
fly2.operate();
fly3.operate();

输出:

AABB-0.8621504916809499

CCDD-0.7498800195753574

CCDD-0.7498800195753574

复合享元模式

1. 复合享元

function UnShareFlyweight() {
  this.state = '';
  this.hash = new Hashtable();
}

UnShareFlyweight.prototype.add = function(key, flyweight) {
  this.hash.add(key, flyweight);
}

UnShareFlyweight.prototype.operate = function(state) {
  var flag = false;
   /*
  for (idx in this.hash) {
    var fly = this.list[idx];
    if (fly.stateOne == state) {
      flag = true;
       break;
    }
  }
   */
  
   flag = this.hash.contain(state);
  flag ? console.log('Exists') : console.log('Not Exists');
}

2. 在修改添加在享元工厂的组合方法:

function FlyweightFactory(){
  var hash = new Hashtable();
}

FlyweightFactory.prototype.getFlyweight = function(state) {
  var flyweight;
  if (hash.contain(state)) {
    flyweight = hash.get(state);
  } else {
    flyweight = new Flyweight(state);
    hash.add(state, flyweight);
  }
  return flyweight;
}

FlyweightFactory.prototype.getComposite = function(list) {
  var unFly = new UnShareFlyweight();
  var flyweight, state;
  for (idx in list) {
    state = list[idx];
    flyweight = this.getFlyweight(state);
    unFly.add(state, flyweight);
  }
}

FlyweightFactory.prototype.print = function() {
  var jsons = this.hash.getJson();
  for (json in jsons) {
    json.value.operate();
  }
}

3. Client 使用:

var states = ['AABB', 'CDCD', 'AABB', 'CCDD'];

var factory = new FlyweightFactory();
factory.getComposite(states);

factory.print();

输出:

AABB-0.8749617566354573

CDCD-0.6991151459515095

CCDD-0.9891050879377872

享元模式其他说明

总体来说,享元模式用于减少对象的重复创建,用于减少内存使用,提升性能的结构型模式:

它涉及三个模式:享元模式,工厂模式,组合模式;

对于处理多对多对应而产生的一些数据缓存存储,是一个不错的选择!

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

(0)

相关推荐

  • js设计模式之结构型享元模式详解

    运用共享技术有效地支持大量的细粒度的对象,避免对象间拥有相同内容造成多余的开销. 享元模式主要是对其数据.方法共享分离,将数据和方法分成内部数据.内部方法和外部数据.外部方法.内部方法与内部数据指的是相似或共有的数据和方法,所以将其提取出来减少开销. var Flyweight = function() { // 已创建的元素 var created = []; // 创建一个新闻包装容器 function create() { var dom = document.createElement(

  • JavaScript 设计模式 安全沙箱模式

    命名空间 JavaScript本身中没有提供命名空间机制,所以为了避免不同函数.对象以及变量名对全局空间的污染,通常的做法是为你的应用程序或者库创建一个唯一的全局对象,然后将所有方法与属性添加到这个对象上. 复制代码 代码如下: /* BEFORE: 5 globals */ // constructors function Parent() {} function Child() {} // a variable var some_var = 1; // some objects var mo

  • 学习JavaScript设计模式之享元模式

    一.定义 享元(flyweight)模式是一种用于性能优化的模式,核心是运用共享技术来有效支持大量细刻度的对象. 在JavaScript中,浏览器特别是移动端的浏览器分配的内存并不算多,如何节省内存就成了一个非常有意义的事情. 享元模式是一种用时间换空间的优化模式 内衣工厂有100种男士内衣.100中女士内衣,要求给每种内衣拍照.如果不使用享元模式则需要200个塑料模特:使用享元模式,只需要男女各1个模特. 二.什么场景下使用享元模式? (1)程序中使用大量的相似对象,造成很大的内存开销 (2)

  • 深入理解JavaScript系列(37):设计模式之享元模式详解

    介绍 享元模式(Flyweight),运行共享技术有效地支持大量细粒度的对象,避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类). 享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生产大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数以外,开销基本相同的 话,就可以大幅度较少需要实例化的类的数量.如果能把那些参数移动到类实例的外面,在方法调用的时候将他们传递进来,就可以通过共享大幅度第减少单个实例 的数目. 那么如果在JavaScript中应用享元模式

  • 总结JavaScript设计模式编程中的享元模式使用

    享元模式不同于一般的设计模式,它主要用来优化程序的性能,它最适合解决大量类似的对象而产生的性能问题.享元模式通过分析应用程序的对象,将其解析为内在数据和外在数据,减少对象的数量,从而提高应用程序的性能. 基本知识 享元模式通过共享大量的细粒度的对象,减少对象的数量,从而减少对象的内存,提高应用程序的性能.其基本思想就是分解现有类似对象的组成,将其展开为可以共享的内在数据和不可共享的外在数据,我们称内在数据的对象为享元对象.通常还需要一个工厂类来维护内在数据. 在JS中,享元模式主要有下面几个角色

  • javascript设计模式 接口介绍

    这本书中第一个重要的内容就是接口. 大家对接口应该都不陌生,简单的说接口就是一个契约或者规范.在强类型的面相对象语言中,接口可以很容易的实现.但是在javascript中并没有原生的创建或者实现接口的方式,或者判定一个类型是否实现了某个接口,我们只能利用js的灵活性的特点,模拟接口. 在javascript中实现接口有三种方式:注释描述.属性验证.鸭子模型. note:因为我看的是英文书,翻译水平有限,不知道有些词汇如何翻译,大家只能领会精神了. 1. 注释描述 (Describing Inte

  • JavaScript 设计模式之组合模式解析

    怎么说呢?!就像是动物(组合对象)一样,当它生下后代(叶对象)时,它的后代就有了某种功能(比如:挖洞,听力好等等):也像是一棵树,它有一个根(组合对象)然后是从这个棵树向外冒出的其他枝杆(组合对象)以及从这些枝杆又向外长的叶子(叶对象).换句话说,就是当祖先已经有了,那么只要从这个祖先衍生出来的其他孩子(包括这个祖先下的其他组合对象)已经就具备了某种功能,看上去貌似又有些像是继承."组合模式"在组合对象的层次体系中有两种类型的对象:叶对象和组合对象.组合模式擅长于对大批对象进行操作.

  • JavaScript设计模式之观察者模式(发布者-订阅者模式)

    观察者模式( 又叫发布者-订阅者模式 )应该是最常用的模式之一. 在很多语言里都得到大量应用. 包括我们平时接触的dom事件. 也是js和dom之间实现的一种观察者模式. 复制代码 代码如下: div.onclick  =  function click (){ alert ( "click' ) } 只要订阅了div的click事件. 当点击div的时候, function click就会被触发. 那么到底什么是观察者模式呢. 先看看生活中的观察者模式. 好莱坞有句名言. "不要给我

  • 学习JavaScript设计模式(链式调用)

    1.什么是链式调用 这个很容易理解,例如: $(this).setStyle('color', 'red').show(); 一般的函数调用和链式调用的区别:调用完方法后,return this返回当前调用方法的对象. function Dog(){ this.run= function(){ alert("The dog is running...."); return this;//返回当前对象 Dog }; this.eat= function(){ alert("Af

  • JavaScript设计模式之享元模式实例详解

    本文实例讲述了JavaScript设计模式之享元模式.分享给大家供大家参考,具体如下: 通过两个例子的对比来凸显享元模式的特点:享元模式是一个为了提高性能(空间复杂度)的设计模式,享元模式可以避免大量非常相似类的开销. 第一实例,没有使用享元模式,计算所花费的时间和空间使用程度. 要求为:有一个城市要进行汽车的登记 (1)汽车类 /** * 制造商 * 型号 * 拥有者 * 车牌号码 * 最近一次登记日期 */ var Car = function(make,model,year,owner,t

  • javascript设计模式之解释器模式详解

    神马是"解释器模式"? 先翻开<GOF>看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如何创建一个抽象语法树.它不涉及语法分析.抽象语法树可用一个表驱动的语法分析程序来完成,也可用手写的(通常为递归下降法)语法分析程序创建,或直接client提供. 解析器: 指的是把描述客户端调用要求的表达式,经过解析,形成一个抽象语法树的程序. 解

随机推荐