javascript设计模式 -- 策略模式

本文介绍策略模式在计算商品价格中的应用,通过重构代码消除if-else语句,提高算法复用性和代码弹性,遵循开放-封闭原则。

前言

本系列文章主要根据《JavaScript设计模式与开发实践》整理而来,其中加入了自己的思考与理解。希望对大家有所帮助。

策略模式思想

定义一系列算法,把它们一个个封装起来,并且使他们可以相互替换。

一个策略模式的程序至少由两部分组成。第一部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二部分是环境Context,Context接受客户的请求,随后把请求委托给某个策略类。要做到这点,说明Context中要维持对某个策略对象的引用。

策略模式应用场景

  • 购买商品,如商品参与满减,打折等活动,多个活动同时参与,并且可以使用优惠券
  • 大量使用if-else语句
  • 相同的目的,但是实现过程,方式不一样, 如:表单验证等

使用策略模式计算商品价格

现在有一款商品,原价200元,参与了打满400打7折活动,并且使用一张满50减10款的优惠券,现在我们要计算出最后需要支付的价格。

1.最初代码实现

const calculatePrice = function(price) {
  const discount = {
    condition: 400,
    preferential: 0.7
  };
  const coupon = {
    condition: 50,
    preferential: 10
  };
  if (price >= discount.condition) {
    price = price * discount.preferential;
  }
  if (price >= coupon.condition) {
    price = price - coupon.preferential;
  }
  return price;
};

console.log(calculatePrice(200));//购买一件商品,使用优惠券,输出190

虽然这段代码很简单,但是可以发现存在显而易见的缺点。

  • calculatePrice函数比较庞大,包含很多if-else语句,这些语句覆盖了所有的逻辑
  • calculatePrice函数缺乏弹性,如果新增一种优惠手段,那么我们必须去修改calculatePrice函数,这种做法违反了开放-封闭原则
  • 算法的复用性差,如果在程序其它地方需要使用这些计算价格的算法,我们只用复制粘贴
    因此,我们需要重构这段代码。

2.使用策略模式重构
记得上面我们说过策略模式的思想:定义一系列算法,把它们一个个都封装起来,并且使它们可以相互替换。策略模式的组成:1.一个策略类,2.一个环境Context,Context响应用户请求并委托给某个策略对象

首先我们先来定义一个策略类:

const strategies = {
  //打折
  discount: function(price, condition, discountVal) {
    return price >= condition ? price * discountVal : price;
  },
  //使用优惠券
  coupon: function(price, condition, couponVal) {
    return price >= condition ? price - couponVal : price;
  }
};

然后我们定义一个环境Context,用于接收用户请求,并委托给某个策略对象进行计算:

const calculatePrice = function(fun, ...params) {
  return fun(...params);
};

重构完毕,我们重新来计算一下支付价格:

const discount = {
  condition: 400,
  preferential: 0.7
};
const coupon = {
  condition: 50,
  preferential: 10
};
let price = calculatePrice(strategies.discount, 200, discount.condition, discount.preferential);
console.log('打折后的价格:'+ price); //输出200
price = calculatePrice(strategies.coupon, price, coupon.condition, coupon.preferential);
console.log('使用优惠券的价格:'+ price); //输出190

通过使用策略模式重构,我们消除了大片的if-else语句。所有跟计算价格有关的算法,都没有存在于Context中,而是分布在各个策略对象中。Context并没有计算能力,而是将这个职责委托给某个策略对象。每个策略对象负责的算法已被封装到各自的对象内部,当我们发起“计算价格”的请求时,它们会根据各自的不同返回结果,这正是对象多态的体现。

策略模式的优缺点

优点
  • 可以有效的避免多重条件选择语句
  • 策略模式提供了对开放-封闭原则的完美支持,将算法独立封装,使它们易于切换,易于理解,易于扩展
  • 易于复用代码
缺点
  • 如果程序中存在大量算法,会造成定义许多策略类或者策略对象
  • 在使用策略模式之前,使用者必须了解每个策略对象的区别,自行决定需要使用哪种策略
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值