策略模式

策略模式(Strategy):将定义的一组算法封装起来,使其相互之间可以替换。封装的算法具有一定的独立性,不会随客户端变化而变化。

其实策略模式在我们生活中可应用的地方还是比较多的,比如在商城搞促销的时候,会有很多打折的情况比如5折呀,7折呀,还会有各种返利,比如满200-100这类的活动,这种场景,我们的策略模式就可以应用上去

示例演示

//创建折扣策略对象
var DiscountStrategy = function() {
//创建内部算法对象
var stragtegy = {
rebate30: function(price) {
return price - parseInt(price / 100) * 30;
},
rebate50: function(price) {
return price - parseInt(price / 100) * 50;
},
discount90: function(price) {
return price * 100 * 90 / 10000
},
discount80: function(price) {
return price * 100 * 80 / 10000
},
discount50: function(price) {
return price * 100 * 50 / 10000
} }
//策略算法调用接口
return { returnPrice: function(algorithm, price) {
return stragtegy[algorithm] && stragtegy[algorithm](price);
},
,//添加策略
addStrategy: function(type, fn) {
stragtegy[type] = fn;
} } }();

我们看一下具体的调用,另外我们之前添加了拓展策略的方法,我们一并测试下

var price = DiscountStrategy.returnPrice('discount50', '210');
console.log(price);
//添加新策略
DiscountStrategy.addStrategy('discount70', function(price) {
return price * 100 * 70 / 10000
})
price = DiscountStrategy.returnPrice('discount70', '210');
console.log(price);

从结构上看,策略模式和状态模式很像,也是在内部封装一个对象,然后通过返回的接口对象实现对内部对象的调用,但是策略模式不需要管理状态、状态间没有依赖关系。策略之间可以相互替换、在策略对象内部保存的是相互独立的一些算法。

让我们再看一个我们实际场景可以应用的验证例子

实例演示

//表单正则验证策略对象
var checkInput = function() {
var stragtegy = {
//判断是否为空
notNull: function(value) {
return /\s/.test(value) ? '请输入内容' : '';
},
//判断是否为一个数字
number: function(value) {
return /^[0-9]+(\.[0-9]+)?$/.test(value) ? '' : '请输入数字'
}
}
return {
//验证接口
check: function(type, value) {
value = value.replace(/^\s+|\s+$/g, '');
return stragtegy[type] ? stragtegy[type](value) : '没有该类型的检测方法'
},
//添加策略
addStrategy: function(type, fn) {
stragtegy[type] = fn;
}
}
}();

同样的我们调用测试下

console.log(checkInput.check('number', 'a'));
console.log(checkInput.check('number', '0'));
checkInput.addStrategy('phone', function(value) {
return /^\d{3}\-\d{8}$|^\d{4}-\d{7}$/.test(value) ? '' : '请输入正确的电话号码';
})
console.log(checkInput.check('phone', '12345678'));
console.log(checkInput.check('phone', '027-12345678'));

总结

策略模式最主要的特点是创建一系列策略算法,没组算法处理的业务都是相同的,只是处理的过程或者处理的结果不一样,所以它们又是可以相互替换的,这样就解决了算法与使用者之间的耦合。在测试层面上讲,由于每组算法相互之间的独立性,该模式更方便与每组算法进行单元测试保证算法的质量。

策略模式的优点

  1. 策略模式封装了一组代码簇,并且封装的代码相互之间独立,便于对算法的重复引用,提高了算法的复用率。
  2. 策略模式与继承相比,在类的继承中继承的方法是被封装在类中,因此当需求很多算法时,就不得不创建出多种类,这样会导致算法与算法的使用者耦合在一起,不利于算法的独立演化,并且在类的外部改变类的算法难度也是极大的。
  3. 同状态模式一样,策略模式也是一种优化分支判断语句的模式,采用策略模式对算法封装使得算法更利于维护。

策略模式的缺点

  1. 由于选择算法的决定权在用户,所以用户就必须了解每种算法的实现,这样就增加了用户对策略模式的使用成本。
  2. 由于每种算法都相互独立,这样对于一些复杂的算法处理相同的逻辑部分无法实现共享,就会造成资源浪费(我们可以用襄垣模式来解决)。

也谢谢大家看到这里:)如果你觉得我的分享还可以请点击推荐,分享给你的朋友让我们一起进步~

好了以上就是本次分享的全部内容,本次示例参考自JavaScript设计模式一书,让我们一点点积累一点点成长,希望对大家有所帮助。

欢迎转载,转载请注明作者,原文出处。

再起航,我的学习笔记之JavaScript设计模式20(策略模式)的更多相关文章

  1. 再起航,我的学习笔记之JavaScript设计模式08(建造者模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前几 ...

  2. 再起航,我的学习笔记之JavaScript设计模式09(原型模式)

    我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 我们 ...

  3. 再起航,我的学习笔记之JavaScript设计模式11(外观模式)

    经过一段时间的学习与分享,我们对创建型设计模式已经有了一定的认识,未来的一段时间里我们将展开新的篇章,开始迈入结构性设计模式的学习. 结构性设计模式与创建型设计模式不同,结构性设计模式更偏向于关注如何 ...

  4. 再起航,我的学习笔记之JavaScript设计模式14(桥接模式)

    桥接模式 桥接模式(Bridge): 在系统沿着多个维度变化的同时,又不增加其复杂度并已达到解耦 从定义上看桥接模式的定义十分难以理解,那么我们来通过示例来演示什么是桥接模式. 现在我们需要做一个导航 ...

  5. 再起航,我的学习笔记之JavaScript设计模式17(模板方法模式)

    模板方法模式 由模板方法模式开始我们正式告别结构型设计模式,开始行为型设计模式的学习分享 行为型设计模式用于不同对象之间职责划分或算法抽象,行为型设计模式不仅仅涉及类和对象,还涉及类或对象之间的交流模 ...

  6. 再起航,我的学习笔记之JavaScript设计模式22(访问者模式)

    访问者模式 概念介绍 访问者模式(Visitor): 针对于对象结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法 解决低版本IE兼容性 我们来看下面这段代码,这段代码,我们封装了一个绑定 ...

  7. 再起航,我的学习笔记之JavaScript设计模式24(备忘录模式)

    备忘录模式 概念介绍 备忘录模式(Memento): 在不破坏对象的封装性的前提下,在对象之外捕获并保存该对象内部的状态以便日后对象使用或者对象恢复到以前的某个状态. 简易分页 在一般情况下我们需要做 ...

  8. 再起航,我的学习笔记之JavaScript设计模式25(迭代器模式)

    迭代器模式 概念介绍 迭代器模式(Iterator): 在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素. 迭代器 程序中的循环是一种利器,循环语句也使我们程序开发更简洁高效,但是有时一遍 ...

  9. 再起航,我的学习笔记之JavaScript设计模式26(解释器模式)

    解释器模式 概念介绍 解释器模式(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 获取元素在页面中的路径 我们都知道获取一个 ...

随机推荐

  1. Redis-简单实现星形主从配置

    高级参考(https://www.zhihu.com/question/21419897) 简单应用场景 现在配置redis 星形 集群, 有三台服务器, 怎样实现? 复制redis.conf两份, ...

  2. Ubuntu超好用软件:markdown编辑器

    Ubuntu上好用的markdown编辑器:typora 安装教程: sudo add-apt-repository ppa:hzwhuang/ss-qt5 sudo apt-get update s ...

  3. react - 解刨组件的多种写法

    一,原始的createClass写法 对于写react组件,很多人第一印象往往是createClass,这是因为createClass是react组件最原始的写法,基本每个学react的人都是接触这种 ...

  4. 程序设计入门——C语言 习题汇总

    <img width="108" height="40" alt="浙江大学" src="http://imgsize.ph ...

  5. cobbler无人值守批量安装Linux系统

    本文目录: 1.1 pxe安装系统 1.2 cobbler基本介绍 1.3 安装和配置cobbler 1.3.1 安装cobbler 1.3.2 配置dhcp和tftp 1.4 cobbler从本地光 ...

  6. HTML5的三种存储方式以及区别

    首先将存储方式前要先知道为什么要使用他:一是利用本地数据,介绍网络请求:二是弱网环境下,高延迟,低带宽,要把数据本地化: 1.本地存储localStorage和sessionStorage 介绍: 存 ...

  7. UML类图及依赖,泛化,关联,聚合,组合,实现

    UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现 类与类图 1) 类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性.操作.关系的对象集合的总称. 2) 在系统中, ...

  8. centos上安装配置java WEB环境_java(转)

    趁着十一期间,好好的写写随笔来记录自己所学.所践和所得,不足之处,欢迎各位拍砖~~~ 工具:Xftp 5.Xshell 5 一.安装jdk 1. 使用Xftp 5把jdk-8u65-linux-x64 ...

  9. scope引起的问题

    背景 执行mvn clean test命令提示部分包不存在,但通过eclipse的clean操作后可以执行mvn test命令 解决方法 mvn clean操作为清空编译的class文件,test的话 ...

  10. spring boot整合jsp的那些坑(spring boot 学习笔记之三)

    Spring Boot 整合 Jsp 步骤: 1.新建一个spring boot项目 2.修改pom文件 <dependency>            <groupId>or ...