博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js设计模式(1)---单例模式、策略模式、代理模式、迭代器
阅读量:4075 次
发布时间:2019-05-25

本文共 3855 字,大约阅读时间需要 12 分钟。

js设计模式系列(1)----此文主要是对<<JavaScript设计模式与开发实践>>一书的范例摘要。

一、单例模式

1、js没有类的概念,如果是字面量对象的方式,那么直接创建的字面量对象就是一个单例对象,如果我们需要兼顾构造函数创建对象以及惰性加载的方式,就可以采用闭包缓存已经创建的对象,详见下面案例:

var getSingle = function(fn) {  // fn是创建对象的方法  var result ;  return function() {    return result || (result = fn.apply(this, arguments)) //result不存在,就创建  }}// 调用getSingle方法,传入一个创建对象的方法。var getInstance = getSingle(function(str) {  return Symbol(str);});// getInstance 就可以用来创建对象var a1 = getInstance('div');var a2 = getInstance('div');console.log(a1 == a2); // 结果为trueconsole.log(Symbol('xx')===Symbol('xx')); // false ,如果创建了二次Symbol对象就肯定是false,这说明只创建了一次symbol对象。

二、策略模式 

策略模式,就是定义一系列的算法,把每一个算法封装成策略类,并且可以使他们互相替换,我们先看看类java预言实现的策略模式

// 2倍绩效的策略(类)var performanceTwo = function () { }performanceTwo.prototype.calculate = function (salary) {  return salary * 2;}// 3倍绩效的策略(类)var performanceThree = function () { };performanceThree.prototype.calculate = function (salary) {  return salary * 3;}// 管理类 (使用策略类的调用者)var Manager = function (salary) {  this.salary = salary; // 原始工资  this.strategy = null;};// 设置策略对象Manager.prototype.setStrategy = function (strategy) {  this.strategy = strategy;};// 得到最终工资 : 使用传入的策略对原始工资作为参数进行计算。Manager.prototype.getBonus = function () {   return this.strategy.calculate(this.salary);};var manager = new Manager(1000);manager.setStrategy(new performanceThree());console.log(manager.getBonus())manager.setStrategy(new performanceTwo());console.log(manager.getBonus());

2、js方法本身就可以作为参数进行传递,即定义不同算法的方法可以随意替换,只要返回值和参数类型符合运行不报错即可,下面演示js的策略模式。

var strategies = {  "S": function (salary) {    return salary * 4;  },  "A": function (salary) {    return salary * 3;  },  "B": function (salary) {    return salary * 2;  }};var calculateBonus = function (level, salary) {  return strategies[level](salary);};

上面把定义策略方法用字符串作为策略组的key,然后调用时,传key值就可以取到对应的策略方法。

三·、代理模式

 其实上面单例模式就是利用了代理模式,扩展了创建对象方法的缓存能力,下面实现一个利用js代理模式缓存方法执行结果的案例。

// 创建缓存方法执行结果的代理方法(类)var createProxyFn = function (fn) {  var cache = {};  return function () {    var args = Array.prototype.join.call(arguments, ',');    if (args in cache) {      return cache[args];    }    return cache[args] = fn.apply(this, arguments);  }};// 乘法函数var mult = function () {  var a = 1;  for (var i = 0; i < arguments.length; i++) {    a = a * arguments[i];  }  return a;};// 加法函数var plus = function () {  var a = 0;  for (var i = 0; i < arguments.length; i++) {    a = a + arguments[i];  }  return a;};// 测试var proxyMult = createProxyFn(mult);var proxyPlus = createProxyFn(plus);console.log(proxyMult(1, 2, 3, 4)); // 输出:24console.log(proxyMult(1, 2, 3, 4)); // 输出:24console.log(proxyPlus(1, 2, 3, 4)); // 输出:10console.log(proxyPlus(1, 2, 3, 4)); // 输出:10

createProxyFn 方法,就是根据arguments参数拼接标记id,如果此id的结果已经计算过,那么从缓存中取,否则,重新计算并且把结果赋值给对应id的缓存属性。

四、迭代器

// 迭代器模式// 1、显示迭代的方式,即把迭代元素遍历,用一个函数参数进行处理。var each_one = function (arr, fn) {  for (let i = 0; i < arr.length; i++) {    fn(arr[i], i);  }}// 显示迭代的使用each_one([1, 2, 3], function (obj, index) {  console.log(obj, index);});// 2、外部迭代器:主要是闭包内维护一个pos变量,来判断获取当前迭代的对象。var Interator = function (obj) {  var pos = 0;  var next = function () {    pos += 1;  }  var hasNext = function () {    pos >= obj.length;  }  var getCurrent = function () {    return obj[pos];  };  return {    next,    hasNext,    getCurrent  }}// 外部迭代器的使用var interator = Interator([1, 2, 3]);while (interator.hasNext()) {  interator.next();  console.log(interator.getCurrent());};// 3、jquery 迭代器 ()$.each = function (obj, callback) {  var value,    i = 0,    length = obj.length,    isArray = isArraylike(obj);  if (isArray) { // 迭代类数组    for (; i < length; i++) {      value = callback.call(obj[i], i, obj[i]);      if (value === false) {        break;      }    }  } else {    for (i in obj) { // 迭代 object 对象      value = callback.call(obj[i], i, obj[i]);      if (value === false) {        break;      }    }  }  return obj;};

 

转载地址:http://beuni.baihongyu.com/

你可能感兴趣的文章
【leetcode】Reorder List (python)
查看>>
【leetcode】Linked List Cycle (python)
查看>>
【leetcode】Candy(python)
查看>>
【leetcode】Sum Root to leaf Numbers
查看>>
【leetcode】Pascal's Triangle II (python)
查看>>
如何成为编程高手
查看>>
本科生的编程水平到底有多高
查看>>
Solr及Spring-Data-Solr入门学习
查看>>
python_time模块
查看>>
python_configparser(解析ini)
查看>>
selenium学习资料
查看>>
从mysql中 导出/导入表及数据
查看>>
HQL语句大全(转)
查看>>
几个常用的Javascript字符串处理函数 spilt(),join(),substring()和indexof()
查看>>
javascript传参字符串 与引号的嵌套调用
查看>>
swiper插件的的使用
查看>>
layui插件的使用
查看>>
JS牛客网编译环境的使用
查看>>
9、VUE面经
查看>>
Golang 数据可视化利器 go-echarts ,实际使用
查看>>