首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊设计模式之策略模式

聊聊设计模式之策略模式

作者头像
Bug开发工程师
发布2018-04-17 13:30:11
5920
发布2018-04-17 13:30:11
举报
文章被收录于专栏:码农沉思录码农沉思录

前言

这几天大部分同学应该都过完年陆陆续续回到工作岗位了,说到过年,最开心的莫过于与家人团聚了,当然除了与家人团聚,最令人振奋的事情就是发年终奖了。说到发年终奖,那可真是几家欢喜几家愁啊。今天我们要谈的不是年终奖的多少,说多了都是泪啊,我们来聊聊年终奖怎么算。年终奖怎么算,相信每个人心里都比较清楚,因为入职的时候一般都会跟HR谈好年终奖的细节。但是对于财务部的人来说就比较头疼了,毕竟他们要算的可是整个公司的人的年终奖,而且每个人的年终奖的计算方式都不一样,这可怎么办呢?接下来我们就用程序来为财务部的人算下整个公司每个人的年终奖。为了简单起见,我们假设年终奖只跟职工的级别和入职年限有关。我们先不用任何模式实现一个最简单的年终奖算法。

不用模式的年终奖算法

首先我们先定义职工类:

职工类只有2个跟奖金计算相关的属性,一个是入职年限seniority,另一个是职位级别rank。其中级别为枚举型Rank,分别有P4,P5,P6三个级别。

接下来我们编写奖金计算类:

可以看到我们对于奖金的计算是先分级别,然后对每个级别再细分成不同入职年限进行计算的。比如对于级别为P4的职工来说,工作年限大于1年的,奖金为2000,工作年限小于1年的奖金为1000,以此类推。

最后我们写一个客户端测试一下:

结果输出如下:

可以看到,对于级别跟入职年限不同的三个人,我们很容易地就计算出了他们的奖金。

虽然年终奖已经算出来了,但是这样实现有没有什么问题呢?首先在这个例子中,我们的级别只有3种,然而在大公司中级别有可能是十几种之多,如果将所有奖金的计算方式都写在一个方法中,那势必会有很多的“if...else...”代码块,很不美观,也很难维护。还有一个问题就是,假如说现在要修改级别为P4的职工的计算方式,那应该怎么办呢?在这种情况下只能直接修改BonusCalculator类的calculateBonus方法,而实际场景中calculateBonus方法可能很复杂,直接在这里面修改的话很容易出现问题。既然如此,有没有比较好的方法能够实现对奖金的计算,又能够适应变化,且便于维护呢?当然有。在这种情况下,我们可以使用策略模式来实现,下文将为大家详细介绍。

策略模式

策略模式是一个计划或者方法,根据给定的输入条件达成一个目标,其意图是将可互换的方法封装在各个独立的类中,并且让每个方法都实现一个公共的操作。这个公共的操作称为策略操作,其实现由各个不同的类完成,这些类的实现虽然不同,但是接口是一致的,因此可以使用相同的接口给用户提供不同的策略进行互换。策略模式可以让一组策略共存,代码互不干扰,同时还将策略的选择逻辑从策略的实现中分离出来。接下来我们就用策略模式来重写上述计算奖金的例子。

使用策略模式

首先我们来定义计算奖金的策略接口:

策略接口BonusCalculatorStrategy有2个抽象方法,accept方法用来判断该策略是否可以用来计算传入的Employee实例的奖金,calculateBonus方法则是具体计算奖金的策略。接着我们来实现具体的奖金计算策略,他们都实现BonusCalculatorStrategy接口。我们根据职位级别的不同分别实现不同的奖金计算策略,分别是P4BonusCalculatorStrategy、P5BonusCalculatorStrategy、P6BonusCalculatorStrategy,他们分别用于计算职位为P4、P5、P6的职工的奖金。由于这三种策略的实现大同小异,这里只列出P4奖金计算策略P4BonusCalculatorStrategy的代码:

由于P4BonusCalculatorStrategy只计算P4级别的职工的奖金,因此在accept方法的实现中,只有职位为P4的职工才会返回true,表示该级别的职工可以使用该策略计算奖金。而calculateBonus方法的实现则是具体的P4级别的职工的奖金计算方法。P5BonusCalculatorStrategy和P6BonusCalculatorStrategy的实现与P4BonusCalculatorStrategy类似,在此不赘述。

既然具体的计算奖金的策略已经实现了,那么我们该如何进行策略的选择呢?前文说到策略模式将策略的实现与策略的选择分开了,上述只是实现了具体的策略,并没有策略选择的逻辑,因此我们这里再引入一个策略上下文,其作用是对策略进行选择:

StrategyContext中持有奖金计算的所有策略,并在静态代码块中初始化所有的奖金计算策略。而getStrategy方法则根据具体的职工实例获取其对应的奖金计算策略,在该方法中,我们遍历了所有的奖金计算策略,调用每种策略的accept方法,如果返回true,则表明该策略适合用于计算该职工的奖金,并将该策略返回给客户端。

最后我们写一个客户端测试一下:

其输出如下:

可以看到,使用策略模式,我们也可以正确地计算出各个职工的奖金。

策略模式的优点

说了这么多,那么策略模式到底有什么优点呢?我们再回到一开始的问题,假如说现在需要修改P4级别的职工的奖金计算方式,那么我们只需要修改P4BonusCalculatorStrategy这个具体的策略就行了,其他地方都不需要修改,这样一来,修改影响到的只是P4BonusCalculatorStrategy这种策略,其他策略并不会受影响。如果不使用策略模式,那么修改的时候需要在“if...else...”块中进行修改,这无疑是很痛苦的事情,也很容易出错。还有就是如果要增加新的策略,比如说现在要计算P7职工的奖金,使用策略模式只需要增加一种策略的实现类,然后在策略上下文中初始化就行了,如果不使用策略模式,则必须增加额外的“if...else...”代码块,相比较而言,使用策略模式代码的可读性跟可维护性大大提升了。

以上就是策略模式的介绍了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农沉思录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 不用模式的年终奖算法
  • 策略模式
  • 使用策略模式
  • 策略模式的优点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档