javascript设计模式详解之策略模式
接上篇命令模式来继续看下js设计模式中另一种常用的模式,策略模式。策略模式也是js开发中常用的一种实例,不要被这么略显深邃的名字给迷惑了。接下来我们慢慢看一下。
一、基本概念与使用场景:
基本概念:定义一系列方法,封装起来使他们可以相互替换。也就是将策略封装在策略类中,当发起请求时管理类将请求委托给对应策略类。
概括而言,就是讲对应不同情况的策略(即不同的处理方法)专门分装在一个对象中,即策略对象里面包含所有的策略。事件请求不直接请求该策略对象,而是有个管理对象来处理请求转发给策略对象的不同接口,这里其实也可以认为涉及到代理模式的概念,不过要申明一点,任何的设计模式都不是单一独立存在的,一种解决方案涉及到两种或者多种的设计模式也是很正常的现象。不要去强行区分到底属于哪种设计模式。 主要目的是为了避免太多的逻辑判断语句的出现,解耦业务逻辑和算法策略。
使用场景:适用于业务逻辑中重复比较多依赖参数或者标识来区分不同的处理的场景。例如react中一个新建某个订单的页面中,存在很多的渲染input等。
二、实例:
假设我们现在有这样一个需求:需要根据form表单元素的不同类型,当点击的时候输出对应的表单元素类型。
分析一下其实很简单,不外乎这下面的几种做法:。
1、简单粗暴流、每个元素都绑定一个事件,依次处理就好:
/** * 每个元素绑定一个事件,分别去输出 */ btn1.onClick(function(){ console.log('btn1 type') }) //n多个 btnN.onClick(function(){ console.log('btnN type') })
2、上面的代码太糟心了,例如10个input就要写10个事件来绑定。可以绑定在同一个事件上,通过判断来处理
1)给各个表单绑定事件,点击的时候将type属性带过去(这个就略过了)
2)针对性的处理事件,用if-else或者switch来判断
/** * 非策略模式 * 根据入参的不同,调用不同的方法,输出对应结果 */ var renderDom = function(type){ if(type == 'text'){ console.log('this is method for text') }else if(type == 'radio'){ console.log('this is method for radio') }else if(type == 'checkbox'){ console.log('this is method for checkbox') }else { console.log('this is method for default') } //也可能这么写 switch(type){ case 'text': console.log('this is method for text') break; case 'radio': console.log('this is method for radio') /** * 余下的省略 * */ } }
3、上面这种写法引入了那么多的逻辑判断,当有更改的时候就需要跟进不同的方法里进行修改了。还是有点麻烦。这时候就可以用策略模式来做了:
/** * 针对不同情况的策略算法封装在策略类fucs中, * 从调用事件中去除繁琐的if或者switch逻辑判断。达到解耦的目的 * 加入后面再增加‘select’的选项增加对应的方法即可 */ var funcs = { text:function(){ console.log('this is method for text') }, radio:function(){ console.log('this is method for radio') }, checkbox:function(){ console.log('this is method for checkbox') }, default:function(){ console.log('this is method for default') } } var renderDom = function(type){ /** * 只需要根据不同的入参,自行匹配策略类中的接口即可。 */ return (funcs[type] || funcs['default'])() } renderDom('checkbox')
简单说下策略模式的思路:
1)所谓的策略对象就是funcs对象,里面的不同属性接口对应的方法就是策略。与逻辑判断分离开,如果有不同的情况的出现,对应的增加属性接口即可。
2)renderDom方法就是对应的管理类了,只需要根据不同的type,去调用funcs不同的方法就好了。如果有改动,这里不需要修改,为了健壮性考虑,如果type没有对应的接口,那就调用默认的default对应接口。
3)调用事件,就保持不变。将tyoe类型传过去就好了。
这样来看,将可变的策略部分封装成了一个对象,不再需要逻辑判断只需要调用策略类对应的接口就行,这样无论从性能,可读性,可扩展性上来讲都比逻辑判好的不是一点半点。
至此策略模式也介绍结束了。可能我们在原来写代码的过程中多多少少的都用到过,只不过没有明确的名称观念罢了。说开了,设计模式也就是为了解决问题而产生的一种思路,没有听起来那么的高大上。切勿为了使用设计模式而强行引入,也切勿不同情况坚持使用某一种设计模式。不要被形式总之快速高效的解决问题才是我们的唯一目的。
相关内容:
参考文章:JavaScript设计模式与开发实践
javascript设计模式详解之策略模式的更多相关文章
- javascript设计模式详解之命令模式
每种设计模式的出现都是为了弥补语言在某方面的不足,解决特定环境下的问题.思想是相通的.只不过不同的设计语言有其特定的实现.对javascript这种动态语言来说,弱类型的特性,与生俱来的多态性,导致某 ...
- Javascript设计模式详解
Javascript常用的设计模式详解 阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javas ...
- JavaScript设计模式与开发实践 - 策略模式
引言 本文摘自<JavaScript设计模式与开发实践> 在现实中,很多时候也有多种途径到达同一个目的地.比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但 ...
- Javascript设计模式学习三(策略模式)
定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换.目的:将算法的使用和算法的实现分离开来.比如: if(input == 'A'){ return 1; } if(input == ...
- JavaScript设计模式(三) - 策略模式
什么是策略模式? 策略模式支持在运行时由使用者选择合适的算法,对于使用者而言不用关心背后的具体实现,由使用者自动根据当前程序执行的上下文和配置,从已有的算法列列表中选择出合适的算法来处理当前任务. ...
- JavaScript设计模式 样例二 —— 策略模式
策略模式(Strategy Pattern): 定义:定义了一族算法: 封装了每个算法: 这族的算法可互换代替. 目的:将算法的使用与算法的实现分离开来. 场景:可用来消除大量的条件分支语句. 例:J ...
- Java常用设计模式详解1--单例模式
单例模式:指一个类有且仅有一个实例 由于单例模式只允许有一个实例,所以单例类就不可通过new来创建,而所有对象都默认有一个无参的构造函数可以创建对象,所以单例类不仅不能提供public的构造方法,还需 ...
- Javascript常用的设计模式详解
Javascript常用的设计模式详解 阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javas ...
- 设计模式详解及PHP实现:代理模式
[目录] 代理模式(Proxy pattern) 代理模式是一种结构型模式,它可以为其他对象提供一种代理以控制对这个对象的访问. 主要角色 抽象主题角色(Subject):它的作用是统一接口.此角色定 ...
随机推荐
- JDBC与ArrayList和hashmao
JDBC帮助类 package work; import java.beans.Statement;import java.sql.Connection;import java.sql.DriverM ...
- Oracle DQL查询语言整理
select * from t_hq_ryxx; select nianl, xingm from t_hq_ryxx; select nianl as 年龄, xingm as 姓名 from t_ ...
- TCP/IP、HTTP、Socke、UDP的区别
一.TCP/IP.Http.Socket的区别 [http://jingyan.baidu.com/article/08b6a591e07ecc14a80922f1.html](http://jing ...
- php获取checkbox数组的表单数据
提交表单的时候,对于checkbox多选框,name="field[]",此时php获取的数组为:从0开始的索引数组:如果name="field[n]" 有数字 ...
- 老李推荐:第3章3节《MonkeyRunner源码剖析》脚本编写示例: MonkeyImage API使用示例 1
老李推荐:第3章3节<MonkeyRunner源码剖析>脚本编写示例: MonkeyImage API使用示例 在上一节的第一个“增加日记”的示例中,我们并没有看到日记是否真的增加成功 ...
- UNION ALL合表查询
有时候需要连表查询数据,可以使用union all来做合表. 语法: SELECT column_name FROM table1UNION ALLSELECT column_name FROM ta ...
- lumen 中的 .env 配置文件简介和适用场景
lumen 是 laravel 的衍生品,核心功能的使用和 laravel 都是一致的,但配置文件这一方面,lumen 在 laravel 的基础上增加了更简便的配置方式: lumen 采用了 Dot ...
- 利刃 MVVMLight 5:绑定在表单验证上的应用
表单验证是MVVM体系中的重要一块.而绑定除了推动 Model-View-ViewModel (MVVM) 模式松散耦合 逻辑.数据 和 UI定义 的关系之外,还为业务数据验证方案提供强大而灵活的支持 ...
- sql server 数值的四舍五入
sql中的四舍五入通常会有round 和cast( …… as decimal())两种方式: 个人建议使用cast 方式: 方式1: 经过试验,同样都可以做到四舍五入,但round如下实例1会报 ...
- 时间同步方法及几个可用的NTP服务器地址
大家都知道计算机电脑的时间是由一块电池供电保持的,而且准确度比较差经常出现走时不准的时候.通过互联网络上发布的一些公用网络时间服务器NTP server,就可以实现自动.定期的同步本机标准时间. 依靠 ...