设计模式在出行平台中的应用与实践

Posted 特来电云计算与大数据

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式在出行平台中的应用与实践相关的知识,希望对你有一定的参考价值。

一、出行计费功能业务背景简介


出行业务涉及多种费用,包括:基础费、起步费、时长费、里程费、长途附加费、等候费、低速费。这些费用的计算有一定的规则。

  •  在乘客上车前,只可能产生等候费。如果存在乘客到达乘车点的时间晚于约定时间,可能收取等候费。

  • 基础费和起步费不能同时存在,并且基础费和起步费需要与时长费、里程费进行综合计算后才能确定最终的收费信息。

  • 如果里程达到一定限度,可能收取长途附加费,计入长途附加费的里程与包含在基础费和起步费的里程有一定关系。

  • 如果行驶速度很低,可能收取低速费。

从上面的场景可以看出:出行的费用计算是有顺序要求的,前面费用计算的结果可能会对后面的费用产生影响。随着业务的发展,每种费用可能产生在不同时间、适用不同客户的新算法。这对代码的可维护性和可扩展性提出了较高的要求。


二、巧用设计模式解决业务扩展性和耦合性问题


相同费用类型的算法间是可以互相替换的,它们都有共同的行为:计算费用。这种场景可以用策略模式来进行扩展。

行程会涉及一系列的费用类型,创建这些费用类型的实例可以用抽象工厂模式。

费用的计算是有顺序要求的,并且具体需要计算哪些费用类型是不固定的。这里可以用建造者模式动态构建费用计算链。

给用户呈现的信息并不完全是所有的费用信息,比如,基础费和起步费的收取需要与时长费、里程费进行综合计算。并且不同的用户关心不同的费用报表。乘客是花钱的一方,所以会关心每一分钟、每一公里的费用明细;司机是收钱方,往往只关心每种费用类型的总额;平台是运营方,往往只关注每笔订单一共产生了多少费用。对相同的结果产生不同的报表,这里可以使用访问者模式。


三、具体代码实现


整体类图如下:

抽象费用计算器AbsFeeCalculator:定义了计算费用的契约。提供了设置下一个费用计算器的方法,用来构建费用计算链条。提供了接受访问者的方法用来将费用信息汇报给用户。

设计模式在出行平台中的应用与实践

计算器抽象工厂AbsFeeCalculatorFactory:定义创建一系列计算器的抽象方法。

设计模式在出行平台中的应用与实践

抽象计算器链建造者AbsFeeChainBuilder:定义向链中增加新计算器和获取第一个费用计算器的方法。

设计模式在出行平台中的应用与实践

计算器链建造调度者FeeChainBuildDirector:定义多种创建计算器链的方法,用于提供适用不同需求的费用计算器链。

设计模式在出行平台中的应用与实践

抽象费用信息访问者AbsFeeInfoReporter:定义对一系列费用进行汇报的抽象方法。

费用信息提供者FeeInfoProvider:调度者通过建造者实例获取计算器链的第一个计算器,设置访问者,计算费用信息,返回汇报结果。


前面的费用计算结果怎样通知后面的费用计算器呢?通过在抽象费用计算器AbsFeeInfoReporter的构造函数入参中增加了一个环境变量的属性,通过这个属性传递了费用计算过程中产生的必要的信息,这样避免了费用计算器之间的互相依赖。


四、设计模式带来的提升


如果不使用设计模式,各种费用的计算逻辑放在一起,每次修改都需要仔细阅读前前后后的大量代码,梳理业务逻辑,然后在一堆if else 中加入新的逻辑分支,改动后很容易引发一连串的错误。这对开发者是一种考验,对后来的维护者更是一种折磨。而使用设计模式改造后,我们可以获得以下收益:

通过使用策略模式,可以根据需求提供新的算法实现类,替换现有算法,实现快速扩展,不影响原有业务逻辑。

通过使用抽象工厂模式,可以提供新的工厂创建适用新场景的一系列算法实现类,选择不同的工厂来灵活的切换一系列的算法。

通过使用责任链模式,行程费用的计算过程形成一个链条,保证了计算的有序性和可配置性。

通过使用建造者模式,可以根据需求,采用不同的配置,调整要计算的费用类型和计算的顺序,封装了具体设置的过程。面对新需求时改动很小,适用性非常强。

通过使用访问者模式,将费用的计算逻辑与呈现逻辑进行了分离,并且根据相同的费用信息,可以获得不同费用信息报表。

因为各个业务对象都依赖抽象对象,符合依赖倒置原则、里氏替换原则,所以在应对这些新变化时,原有代码不需要大范围调整这样。设计模式给了我们一些适用特定场景的解决方案,可以用这些方案来帮助我们规划业务处理方式,提高代码的可维护性和可扩展性。


五、关于面向对象的一些心得体会


业务的逻辑可能比较复杂,我们需要根据单一职责分离出不同的对象,封装对象自身的属性和行为,既要限制外部对自身信息的访问和更新,又要减少对外部对象的了解。对于对象间的关系,尽量使用关联和聚合,减少继承的层次。

业务的发展会呈现出多样性,提高可维护性和可扩展性需要让对象的创建、结构和行为可以自由定制。为了实现这个目标必须依赖于抽象(接口和抽象类),减少对象的数量(单例模式、享元模式)和对象间的联系(命令模式、观察者模式、中介者模式、门面模式),将对象自身逻辑与附加逻辑分离(代理模式、访问者模式),并努力让这个被依赖的对象可以动态构建(责任链、装饰链、状态流转链)。这样我们就构建了一套面向契约的业务流程,各个业务内部的逻辑被封装,后续需要扩展出多样化的实现时,其他业务模块不需要改动,最终符合了开闭原则,软件的可维护性和可扩展性得到了改善。


以上是关于设计模式在出行平台中的应用与实践的主要内容,如果未能解决你的问题,请参考以下文章

Android 组件化实践 - 回溯 设计 实现

面向机器学习:数据平台设计与搭建实践

滴滴出行数据应用平台建设实践

HBase在滴滴出行的应用场景和最佳实践

推荐系统在滴滴司机调度系统中的应用实践

江苏农信 SDN 技术应用在云平台架构设计实践经验 | 最佳实践