JavaScript设计模式(二)策略模式 代理模式

定义一系列的算法,把它们各自封装成策略类,算法被封装在策略类内部的方法里。在客户对Context发起请求的时候,Context总是把请求委托给策略对象中间的某一个进行计算。

一、策略模式

1.基本策略模式

计算某公司员工绩效,S奖金4,A3,B*2

(1)基本实现

let calculate = function (level, salary) {
  if (level === 'S') {
    return salary * 4;
  }
  if (level === 'A') {
    return salary * 3;
  }
  if (level === 'B') {
    return salary * 2;
  }
}

以上代码实现了一个基本的计算功能,但是该函数会随着业务的复杂程度而变得更加复杂(因为主要是使用if-else语句实现的),且函数的复用性不强。

(2)考虑使用组合函数来重构代码

let funcA = function (salary) {
  return salary * 4;
}
let funB = function (salary) {
  return salary * 3;
}
let funC = function (salary) {
  return salary * 2;
}

let calculate = function (level, salary) {
  if (level === 'S') {
    return funcA(salary);
  }
  if (level === 'A') {
    return funcA(salary);
  }
  if (level === 'B') {
    return funcB(salary);
  }
}

以上代码针对之前的写法有了一定的优化,但是仍然没有改变calculate会变得越来越庞大且缺乏弹性的问题。

(3)使用策略模式

let funcS = function () { };
funcS.prototype.calculate = function (salary) {
  return salary * 4;
}
let funcA = function () { };
funcA.prototype.calculate = function (salary) {
  return salary * 3;
}
let funcB = function () { };
funcB.prototype.calculate = function (salary) {
  return salary * 2;
}

let Bouns = function () {
  this.salary = null;
  this.salary = null;
}
Bouns.prototype.setSalary = function (salary) {
  this.salary = salary;
}
Bouns.prototype.setStrategy = function (strategy) {
  this.strategy = strategy;
}
Bouns.prototype.getBonus = function () {
  if (!this.strategy) {
    throw new Error('未设置strategy属性');
  }
  return this.strategy.calculate(this.salary);
}

最后使用策略模式重构了代码,重构后的代码更加清晰,各个类的职责更加鲜明。以上是基于面向对象语言的策略模式,关于JavaScript还有它自身的策略模式的实现。

2.JavaScript版本的策略模式

let strategies = {
  'S': function (salary) {
    return salary * 4;
  },
  'A': function (salary) {
    return salary * 3;
  },
  'B': function (salary) {
    return salary * 2;
  }
}

let calculate = function (level, salary) {
  return strategies[level](salary);
}

以上代码利用JavaScript的特性实现了策略模式,在JavaScript中函数也是对象,所以可以直接将各个策略定义成函数,同时奖金类在JavaScript中同样可以用函数来代替。

二、代理模式

为一个对象提供一个代用品或占位符,以便控制对它的访问

1.基本代理

let temp = {
  send: (target) => {
    let value = 1;
    target.receive(value);
  }
}
let A = {
  receive(value) {
    B.receive(value);
  }
}
let B = {
  receive(value) {
    console.log(value);
  }
}

temp.send(A); //1

以上代码实现了一个基本的代理模式

2.虚拟代理

虚拟代理把一些开销很大的对象,延迟到真正需要它的时候才去创建。

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

let proxyImg = (function () {
  let img = new Image;
  img.onload = function () {
    Image.setSrc(this.src);
  }
  return {
    setSrc: function (src) {
      Image.setSrc('loading.gif');
      img.src = src;
    }
  }
})();

Image.setSrc('http://volit.com/1.png');

以上代码使用虚拟代理模式实现了一个图片预加载功能,在图片加载完成之前,先用一张加载gif动图来代替原图片

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

volit_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值