JavaScript设计模式——策略模式

    策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

    俗话说,条条大路通罗马。在美剧《越狱》中,主角 Michael Scofield 就设计了两条越狱的道路。这两条道路都可以到达靠近监狱外墙的医务室。

    同样,在现实中,很多时候也有多种途径到达同一个目的地。比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路。

     如果没有时间但是不在乎钱,可以选择坐飞机。

     如果没有钱,可以选择坐大巴或者火车。

     如果再穷一点,可以选择骑自行车。


    在程序设计中,我们也常常遇到类似的情况,要实现某一个功能有多种方案可以选择。比如一个压缩文件的程序,既可以选择 zip 算法,也可以选择 gzip 算法。

    这些算法灵活多样,而且可以随意互相替换。这种解决方案就是策略模式。

使用策略模式计算奖金

    策略模式有着广泛的应用。我们以年终奖的计算为例进行介绍。

    很多公司的年终奖是根据员工的工资基数和年底绩效情况来发放的。例如,绩效为 S 的人年终奖有 4 倍工资,绩效为 A 的人年终奖有 3 倍工资,而绩效为 B 的人年终奖是 2 倍工资。假设财务部要求我们提供一段代码,来方便他们计算员工的年终奖。

1. 最初的代码实现

    我们可以编写一个名为 calculateBonus 的函数来计算每个人的奖金数额。很显然,calculateBonus 函数要正确工作,就需要接收两个参数:员工的工资数额和他的绩效考核等级。

代码如下:

var calculateBonus = function( performanceLevel, salary ){

    if ( performanceLevel === 'S' ){

        return salary * 4;

    }

    if ( performanceLevel === 'A' ){

        return salary * 3;

    }

    if ( performanceLevel === 'B' ){

        return salary * 2;

    }

};

calculateBonus( 'B', 20000 ); // 输出:40000

calculateBonus( 'S', 6000 ); // 输出:24000

可以发现,这段代码十分简单,但是存在着显而易见的缺点。

     calculateBonus 函数比较庞大,包含了很多 if-else 语句,这些语句需要覆盖所有的逻辑分支。

     calculateBonus 函数缺乏弹性,如果增加了一种新的绩效等级 C,或者想把绩效 S 的奖金系数改为 5,那我们必须深入 calculateBonus 函数的内部实现,这是违反开放封闭原则的。

     算法的复用性差,如果在程序的其他地方需要重用这些计算奖金的算法呢?我们的选择只有复制和粘贴。

使用策略模式重构代码

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

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

    一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类,策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类 Context,Context 接受客户的请求,随后把请求委托给某一个策略类。要做到这点,说明 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 ]( salary );

};

console.log( calculateBonus( 'S', 20000 ) ); // 输出:80000

console.log( calculateBonus( 'A', 10000 ) ); // 输出:30000

策略模式的优缺点

    策略模式是一种常用且有效的设计模式,策略模式的一些优点。

     策略模式利用组合、委托和多态等技术和思想,可以有效地避免多重条件选择语句。

     策略模式提供了对开放—封闭原则的完美支持,将算法封装在独立的 strategy 中,使得它们易于切换,易于理解,易于扩展。

     策略模式中的算法也可以复用在系统的其他地方,从而避免许多重复的复制粘贴工作。

     在策略模式中利用组合和委托来让 Context 拥有执行算法的能力,这也是继承的一种更轻便的替代方案。

    当然,策略模式也有一些缺点,但这些缺点并不严重。

    首先,使用策略模式会在程序中增加许多策略类或者策略对象,但实际上这比把它们负责的逻辑堆砌在 Context 中要好。

    其次,要使用策略模式,必须了解所有的 strategy,必须了解各个 strategy 之间的不同点,这样才能选择一个合适的 strategy。比如,我们要选择一种合适的旅游出行路线,必须先了解选择飞机、火车、自行车等方案的细节。此时 strategy 要向客户暴露它的所有实现,这是违反最少知识原则的。

                                                          ——摘自《JavaScript设计模式与开发实践 》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,717评论 2 17
  • 转载:https://www.cnblogs.com/tugenhua0707/p/4722696.html理解j...
    Picidae阅读 293评论 0 1
  • 1、策略模式的定义是: 定义一系列的算法, 把它们一个个封装起来, 并且使它们可以相互替换。 不变的部分和变化的部...
    spfi阅读 1,242评论 0 100
  • 策略模式的定义:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。 将不变的部分和变化的部分隔开是每...
    peppermint_egg阅读 1,579评论 0 0
  • 偶然的机会认识的简书,便喜欢上这儿。可以学习,可以发表,可以互动,虽然初来乍到,没认识几个人,还是兴致盎然的写着,...
    sun静待花开阅读 111评论 0 2