JavaScript设计模式 Item 7 --策略模式Strategy_ item[strategy 1]

};

var calculateBonus = function( performanceLevel, salary ){

if ( performanceLevel === 'S' ){
    return performanceS( salary );
}

if ( performanceLevel === 'A' ){
    return performanceA( salary );
}

if ( performanceLevel === 'B' ){
    return performanceB( salary );
}

};
calculateBonus( ‘A’ , 10000 ); // 输出:30000


目前,我们的程序得到了一定的改善,但这种改善非常有限,我们依然没有解决最重要的问题:calculateBonus函数有可能越来越庞大,而且在系统变化的时候缺乏弹性。


**3. 使用策略模式重构代码**


经过思考,我们想到了更好的办法——使用策略模式来重构代码。策略模式指的是定义一系列的算法,把它们一个个封装起来。将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。


在这个例子里,算法的使用方式是不变的,都是根据某个算法取得计算后的奖金数额。而算法的实现是各异和变化的,每种绩效对应着不同的计算规则。


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


现在用策略模式来重构上面的代码。第一个版本是模仿传统面向对象语言中的实现。我们先把每种绩效的计算规则都封装在对应的策略类里面:



var performanceS = function(){};

performanceS.prototype.calculate = function( salary ){
return salary * 4;
};

var performanceA = function(){};

performanceA.prototype.calculate = function( salary ){
return salary * 3;
};

var performanceB = function(){};

performanceB.prototype.calculate = function( salary ){
return salary * 2;
};


接下来定义奖金类Bonus:



var Bonus = function(){
this.salary = null; //原始工资
this.strategy = null; //绩效等级对应的策略对象
};

Bonus.prototype.setSalary = function( salary ){
this.salary = salary; //设置员工的原始工资
};

Bonus.prototype.setStrategy = function( strategy ){
this.strategy = strategy; //设置员工绩效等级对应的策略对象
};

Bonus.prototype.getBonus = function(){ //取得奖金数额
return this.strategy.calculate( this.salary ); //把计算奖金的操作委托给对应的策略对象
};


在完成最终的代码之前,我们再来回顾一下策略模式的思想:


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


这句话如果说得更详细一点,就是:定义一系列的算法,把它们各自封装成策略类,算法被封装在策略类内部的方法里。在客户对Context发起请求的时候,Context总是把请求委托给这些策略对象中间的某一个进行计算。


“并且使它们可以相互替换”,这句话在很大程度上是相对于静态类型语言而言的。因为静态类型语言中有类型检查机制,所以各个策略类需要实现同样的接口。当它们的真正类型被隐藏在接口后面时,它们才能被相互替换。而在JavaScript这种“类型模糊”的语言中没有这种困扰,任何对象都可以被替换使用。因此,JavaScript中的“可以相互替换使用”表现为它们具有相同的目标和意图。


现在我们来完成这个例子中剩下的代码。先创建一个bonus对象,并且给bonus对象设置一些原始的数据,比如员工的原始工资数额。接下来把某个计算奖金的策略对象也传入bonus对象内部保存起来。当调用bonus.getBonus()来计算奖金的时候,bonus对象本身并没有能力进行计算,而是把请求委托给了之前保存好的策略对象:



var bonus = new Bonus();

bonus.setSalary( 10000 );
bonus.setStrategy( new performanceS() ); //设置策略对象

console.log( bonus.getBonus() ); // 输出:40000

bonus.setStrategy( new performanceA() ); //设置策略对象
console.log( bonus.getBonus() ); // 输出:30000


刚刚我们用策略模式重构了这段计算年终奖的代码,可以看到通过策略模式重构之后,代码变得更加清晰,各个类的职责更加鲜明。但这段代码是基于传统面向对象语言的模仿,下一节我们将了解用JavaScript实现的策略模式。


在5.1节中,我们让strategy对象从各个策略类中创建而来,这是模拟一些传统面向对象语言的实现。实际上在JavaScript语言中,函数也是对象,所以更简单和直接的做法是把strategy直接定义为函数:



var strategies = {
“S”: function( salary ){
return salary * 4;
},
“A”: function( salary ){
return salary * 3;
},
“B”: function( salary ){
return salary * 2;
}
};


同样,Context也没有必要必须用Bonus类来表示,我们依然用calculateBonus 函数充当Context来接受用户的请求。经过改造,代码的结构变得更加简洁:



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 ;
};

console.log( calculateBonus( ‘S’, 20000 ) ); // 输出: 80000
console.log( calculateBonus( ‘A’, 10000 ) ); // 输出: 30000


### 3、实例再讲解


一个小例子就能让我们一目了然。   
 回忆下jquery里的animate方法.



$( div ).animate( {“left: 200px”}, 1000, ‘linear’ );
//匀速运动
$( div ).animate( {“left: 200px”}, 1000, ‘cubic’ );
//三次方的缓动


这2句代码都是让div在1000ms内往右移动200个像素. linear(匀速)和cubic(三次方缓动)就是一种策略模式的封装.


再来一个例子. 很多页面都会有个即时验证的表单. 表单的每个成员都会有一些不同的验证规则.


![这里写图片描述](https://img-blog.csdn.net/20151106202800284)


比如姓名框里面, 需要验证非空,敏感词,字符过长这几种情况。 当然是可以写3个`if else`来解决,不过这样写代码的扩展性和维护性可想而知。如果表单里面的元素多一点,需要校验的情况多一点,加起来写上百个`if else`也不是没有可能。


所以更好的做法是把每种验证规则都用策略模式单独的封装起来。需要哪种验证的时候只需要提供这个策略的名字。就像这样:



#### 总结

=============================================================

从转行到现在,差不多两年的时间,虽不能和大佬相比,但也是学了很多东西。我个人在学习的过程中,习惯简单做做笔记,方便自己复习的时候能够快速理解,现在将自己的笔记分享出来,和大家共同学习。



个人将这段时间所学的知识,分为三个阶段:

第一阶段:HTML&CSS&JavaScript基础



![](https://img-blog.csdnimg.cn/img_convert/3e0d5b0f6a97b823cc1ef22ff1a18191.png)

第二阶段:移动端开发技术



![](https://img-blog.csdnimg.cn/img_convert/fc21db0a800494796dc6408ce1486031.png)



第三阶段:前端常用框架



![](https://img-blog.csdnimg.cn/img_convert/644efd4ddd0f8d43535f1982ec0da6e4.png)



*   推荐学习方式:针对某个知识点,可以先简单过一下我的笔记,如果理解,那是最好,可以帮助快速解决问题;如果因为我的笔记太过简陋不理解,可以关注我以后我还会继续分享。



*   大厂的面试难在,针对一个基础知识点,比如JS的事件循环机制,不会上来就问概念,而是换个角度,从题目入手,看你是否真正掌握。所以对于概念的理解真的很重要。


  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript 设计模式是在 JavaScript 编程中经常使用的一种代码组织和架构方法。设计模式可以帮助开发者解决常见的问题,并提供可复用的解决方案。 以下是一些常见的 JavaScript 设计模式: 1. 工厂模式(Factory Pattern):通过使用工厂方法创建对象,将对象的创建和使用分离开来,提高代码的可扩展性和可维护性。 2. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点来访问该实例。 3. 观察者模式(Observer Pattern):定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会被自动通知并更新。 4. 发布-订阅模式(Publish-Subscribe Pattern):也是一种观察者模式的变体,在这种模式中,发布者(Publisher)和订阅者(Subscriber)之间通过消息队列进行通信。 5. 原型模式(Prototype Pattern):通过复制现有对象来创建新对象,避免了使用类进行实例化的复杂性。 6. 适配器模式(Adapter Pattern):将一个类的接口转换成客户端所期望的另一个接口,使得原本不兼容的类可以一起工作。 7. 装饰者模式(Decorator Pattern):动态地给对象添加新的功能,而不影响其他对象。 8. 策略模式Strategy Pattern):定义一系列算法,将每个算法封装起来,并使它们可以互换使用。 这些设计模式可以帮助开发者在编写 JavaScript 代码时更好地组织和设计代码结构,提高代码的可读性、可维护性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值