一直觉得设计模式是非常高端的东西,之前也简单的了解过一些,但总是没有找到合适的应用场景,所以也没能深入的去理解他。直到最近在工作中,需要写一个通话记录的功能,每个记录后边要显示该条记录是多久之前产生的。写完的时候用了很多的if else来判断,看起来很不优雅,请教了leader之后,给我指点了一下,按照思路尝试之后,一下子有种豁然开朗的感觉。其实设计模式并非高不可攀或是难以应用的东西,很多代码只要我们尝试去优化他,多想想其他的方式,就能摸到一点设计模式的门槛。所以今天就来记录分享一下这个场景。
参考资料:
策略模式介绍
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
实际应用场景:
需要写一个通话记录的功能,每个记录后边要显示该条记录是多久之前产生的。写完的时候用了很多的if else来判断时间,看起来很不优雅,在这里就可以用到策略模式的思路。把判断条件写成一个对象数组,然后直接遍历数组来得到结果,这样代码优雅,也便于后续的扩展和维护,非常棒棒。
代码:
intervalConfig: [{
min: 60,
divisor: 1,
text: '秒前'
},{
min: 60 * 60,
divisor: 60,
text: '分钟前'
},{
min: 60 * 60 * 24,
divisor: 60 * 60,
text: '小时前'
},{
min: 60 * 60 * 24 * 7,
divisor: 60 * 60 * 24,
text: '天前'
},{
min: 60 * 60 * 24 * 7 * 30,
divisor: 60 * 60 * 24 * 7,
text: '周前'
},{
min: 60 * 60 * 24 * 356,
divisor: 60 * 60 * 24 * 30,
text: '月前'
},{
min: 60 * 60 * 24 * 356 * 999,
divisor: 60 * 60 * 24 * 356,
text: '年前'
}],
// 支持整数,Date,时间字符串三种格式转为时间戳
toTs(t) {
return new Date(t).getTime()
},
now() {
return Date.parse(new Date())
},
// 返回from距今还有多久
getTimeInterval(from) {
let fromTs = toTs(from)
let seconds, index, config, n
seconds = (now() - fromTs) / 1000
index = intervalConfig.findIndex(item => {
return item.min > seconds
})
config = intervalConfig[index]
n = Math.floor(seconds / config.divisor)
return n + config.text
}
结果显示: