js设想形式--代办形式

媒介

本系列文章重要依据《JavaScript设想形式与开辟实践》整顿而来,个中会加入了一些本身的思索。愿望对人人有所协助。

文章系列

js设想形式–单例形式

js设想形式–战略形式

js设想形式–代办形式

观点

代办形式是为一个对象供应一个代用品或占位符,以便掌握对它的接见。

UML类图

《js设想形式--代办形式》

场景

比方,明星都有经纪人作为代办。假如想请明星来办一场贸易上演,只能联络他的经纪人。经纪人会把贸易上演的细节和酬劳都谈好今后,再把合同交给明星签。

分类

庇护代办

于掌握差别权限的对象对目的对象的接见,如上面明星经纪人的例子

假造代办

把一些开支很大的对象,延晚到真正须要它的时刻才去建立。
如短时间内提议很多个http要求,我们可以用假造代办完成肯定时间内的要求一致发送

优瑕玷

长处

1. 可以庇护对象
2. 优化机能,削减开支很大的对象
3. 缓存效果

例子

图片预加载

加载一张图片

  var myImage = (function () {
    var imgNode = document.createElement('img');
    document.body.appendChild(imgNode);
    return {
      setSrc: function (src) {
        imgNode.src = src;
      }
    }
  })();
  myImage.setSrc('https://segmentfault.com/img/bVbmvnB?w=573&h=158');

设想一下,假如我们的图片很大,用户就会看到页面很长一段时间是空缺
我们可以想到的革新是图片加载完成之前都展现loading图片

加个loading图片

var myImage = (function () {
  var imgNode = document.createElement('img');
  document.body.appendChild(imgNode);
  var img = new Image()
  img.onload = () => {
    // 模仿图片加载
    setTimeout(() => {
      imgNode.src = img.src
    }, 1000)
  }
  return {
    setSrc: function (src) {
      img.src = src
      imgNode.src = 'https://content.igola.com/static/WEB/images/other/loading-searching.gif';
    }
  }
})();
myImage.setSrc('https://segmentfault.com/img/bVbmvnB?w=573&h=158');

这段代码违犯了单一职责准绳,这个对象同时负担了加载图片和预加载图片两个职责
同时也违犯了开放关闭准绳,假如我们今后不须要预加载图片了,那我们不能不修正全部对象

用假造代办革新


var myImage = (function () {
  var imgNode = document.createElement('img');
  document.body.appendChild(imgNode);
  return {
    setSrc: function (src) {
      imgNode.src = src
    }
  }
})();

var proxyImage = (function() {
  var img = new Image()
  img.onload = function() {
    myImage.setSrc(img.src)
  }
  return {
    setSrc: function (src) {
      img.src = src
      myImage.setSrc('https://content.igola.com/static/WEB/images/other/loading-searching.gif')
  }
  }
})()


proxyImage.setSrc('https://segmentfault.com/img/bVbmvnB?w=573&h=158');

注重:我们的代办和本体接口要坚持一致性,如上面proxyImage和myImage都返回一个包括setSrc要领的对象。居于这点我们写代办的时刻也有迹可循。

假造代办兼并HTTP要求

简朴的完成

<body>
  <div id="wrapper">
    <input type="checkbox" id="1"></input>1
    <input type="checkbox" id="2"></input>2
    <input type="checkbox" id="3"></input>3
    <input type="checkbox" id="4"></input>4
    <input type="checkbox" id="5"></input>5
    <input type="checkbox" id="6"></input>6
    <input type="checkbox" id="7"></input>7
    <input type="checkbox" id="8"></input>8
    <input type="checkbox" id="9"></input>9
  </div>
</body>

<script type="text/javascript">
  // 模仿http要求
  var synchronousFile = function (id) {
    console.log('最先同步文件,id 为: ' + id);
  };

  var inputs = document.getElementsByTagName('input')
  var wrapper = document.getElementById('wrapper')
  wrapper.onclick = function (e) {
    if (e.target.tagName === 'INPUT') {
      synchronousFile(e.target.id)
    }
  }
</script>

瑕玷很明显:每点一次就发送一次http要求

革新


<body>
  <div id="wrapper">
    <input type="checkbox" id="1"></input>1
    <input type="checkbox" id="2"></input>2
    <input type="checkbox" id="3"></input>3
    <input type="checkbox" id="4"></input>4
    <input type="checkbox" id="5"></input>5
    <input type="checkbox" id="6"></input>6
    <input type="checkbox" id="7"></input>7
    <input type="checkbox" id="8"></input>8
    <input type="checkbox" id="9"></input>9
  </div>
</body>

<script type="text/javascript">
  // 模仿http要求
  var synchronousFile = function (id) {
    console.log('最先同步文件,id 为: ' + id);
  };

  var inputs = document.getElementsByTagName('input')
  var wrapper = document.getElementById('wrapper')
  wrapper.onclick = function (e) {
    if (e.target.tagName === 'INPUT' && e.target.checked) {
      proxySynchronousFile(e.target.id)
    }
  }

  var proxySynchronousFile = (function () {
    var cacheIds = [],
      timeId = 0
    return function (id) {
      if (cacheIds.indexOf(id) < 0) {
        cacheIds.push(id)
      }
      clearTimeout(timeId)
      timeId = setTimeout(() => {
        synchronousFile(cacheIds.join(','))
        cacheIds = []
      }, 1000)
    }
  })()
</script>

缓存代办-盘算乘积

粗拙的完成

var mult = function () {
    console.log('最先盘算乘积');
    var a = 1;
    for (var i = 0, l = arguments.length; i < l; i++) {
      a = a * arguments[i];
    }
    return a;
  };
  mult(2, 3); // 输出:6
  mult(2, 3, 4); // 输出:24

革新


var mult = function () {
  console.log('最先盘算乘积');
  var a = 1;
  for (var i = 0, l = arguments.length; i < l; i++) {
    a = a * arguments[i];
  }
  return a;
};
// mult(2, 3); // 输出:6
// mult(2, 3, 4); // 输出:24

var proxyMult = (function() {
  var cache = {}
  return function () {
    let id = Array.prototype.join.call(arguments, ',')
    if (cache[id]) {
      return cache[id]
    } else {
      return cache[id] = mult.apply(this, arguments)
    }
  }
})()

proxyMult(2, 3); // 输出:6
proxyMult(2, 3); // 输出:6

我们如今愿望加法也可以缓存

再革新


var mult = function () {
  console.log('最先盘算乘积');
  var a = 1;
  for (var i = 0, l = arguments.length; i < l; i++) {
    a = a * arguments[i];
  }
  return a;
};

var plus = function () {
  console.log('最先盘算和');
  var a = 0;
  for (var i = 0, l = arguments.length; i < l; i++) {
    a = a + arguments[i];
  }
  return a;
};


// mult(2, 3); // 输出:6
// mult(2, 3, 4); // 输出:24

var createProxyFactory = function (fn) {
  var cache = {}
  return function () {
    let id = Array.prototype.join.call(arguments, ',')
    if (cache[id]) {
      return cache[id]
    } else {
      return cache[id] = fn.apply(this, arguments)
    }
  }
}

var proxyMult = createProxyFactory(mult),
  proxyPlus = createProxyFactory(plus);
proxyMult(1, 2, 3, 4) // 输出:24
proxyMult(1, 2, 3, 4) // 输出:24
proxyPlus(1, 2, 3, 4) // 输出:10
proxyPlus(1, 2, 3, 4) // 输出:10

es6的代办形式

基于类完成

class Car {
    drive() {
        return "driving";
    };
}

class CarProxy {
    constructor(driver) {
        this.driver = driver;
    }
    drive() {
        return  ( this.driver.age < 18) ? "too young to drive" : new Car().drive();
    };
}

class Driver {
    constructor(age) {
        this.age = age;
    }
}

基于Proxy完成


// 明星
let star = {
    name: '张XX',
    age: 25,
    phone: '13910733521'
}

// 经纪人
let agent = new Proxy(star, {
    get: function (target, key) {
        if (key === 'phone') {
            // 返回经纪人本身的手机号
            return '18611112222'
        }
        if (key === 'price') {
            // 明星不报价,经纪人报价
            return 120000
        }
        return target[key]
    },
    set: function (target, key, val) {
        if (key === 'customPrice') {
            if (val < 100000) {
                // 最低 10w
                throw new Error('价钱太低')
            } else {
                target[key] = val
                return true
            }
        }
    }
})

// 主办方
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)

// 想本身供应报价(砍价,或许高价争抢)
agent.customPrice = 150000
// agent.customPrice = 90000  // 报错:价钱太低
console.log('customPrice', agent.customPrice)
    原文作者:aoping
    原文地址: https://segmentfault.com/a/1190000017743794
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞