几年前写过一个网约车项目,现在回想回想,看看能不能作为项目背景写。
网络预约出租车汽车监管信息交互平台总体技术要求 - 道客巴巴 (doc88.com)
准备三篇:
2020年3月,本人参与了广东省的某网约车项目的开发。此时,本公司已经稳定运行了新能源充电桩项目和新能源共享汽车项目,为了进一步提高公司的新能源汽车综合运营能力,打造一体化的电动汽车综合运营服务网络。在了解了交通部《网络预约出租车监管信息交互平台总体技术要求(暂行)》的要求之后,本公司决定发起新能源网约车项目,在此车项目中,本人担任系统架构师一职,负责项目的系统架构与中间件选型。 新能源网约车以spring alibaba cloud微服务架构为核心,涵盖客户端、司机端、运营端等多个业务模块,本文主要论述了软件设计模式在本系统部分模块中的运用,主要包括创建型模式中的建造者模式和行为型模式中的策略模式与责任链模式。
项目背景:
2020年,本公司已获得多省市的新能源充电设施运营商资质,业务范围覆盖了充电基础设施建设运营和新能源汽车综合运营等领域,并参与了多地的新能源汽车推广应用试点工作。当此之时,本公司充电桩业务方面已经有上千家自营和合作网点,包括公共停车场、物业停车场、事企业单位、大型充电站、汽车租赁公司等。而共享汽车也在深圳和安徽两地展开积极的推广。在此基础上,我司积极响应国家的“碳达峰、碳中和”战略,积极发展新能源,助力可持续发展,因此新能源网约车项目应运而生,主要致力于解决绿色出行问题,推动公司新能源一体化布局。
在此新能源网约车项目,总体分为一下部分:
正文:
通过上述项目的简单描述,可知新能源网约车项目业务比较复杂,且模块较多,模块间的交互比较复杂,联系也比较紧密,如果不能很好的设计模块与编码,可能无法很好的实现高内聚和低耦合的要求,会给软件的扩展和维护带来很多困难。在这种情况下,我们要求程序员在编码的时候,不但要严格遵守日常的编码规范,同时也要注意合理的使用设计模式,设计出结构合理、易用复用和可维护的软件。在当需求发生变化的时候,可通过修改尽量少的代码就可以满足新的功能需求,增强系统的可修改性和稳定性,降低系统的开发成本。
一般而言,设计模式是一套被反复使用的、多数人知晓的代码经验和解决方案,它站在前人的肩膀上,指导新项目中的一些场景的开发和设计,带来更好的灵活性、可拓展性和可复用性。一个设计模式一般包括模式名称、适应场景、解决方案和效果四个方面的基本要素。设计模式依据其目的可以分为创建型设计模式、结构型设计模式和行为型设计模式。其中,创建型设计模式主要用于创建对象,为设计类实例化新对象提供指南。常见的创建型设计模式有:单例模式、工厂方法、原型模式、建造者模式、抽象工厂模式等。结构型模式,一般用以处理类和对象的组合,对类如何设计以形成更大的结构提供指南。结构型设计模式一般包括:适配器模式、桥接模式、装饰器模式、组合模式、外观模式、享元模式、代理模式等。行为型设计模式,一般用于描述类或对象的交互以及职责分配,对类之间的交互和职责分配的方式提供指南。为型设计模式一般包括:责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板模式、访问者模式等。
在新能源网络车项目的开发过程中,我们综合使用了多种设计模式,本文组要对策略模式、建造者模式两者种设计模式在项目中的具体使用进行介绍,
** 一、策略模式在发送消息中的使用**
在新能源网约车项目中,我们需要针对不同的场景给不同的用户发送不同类型的消息。比如,给客户发送注册成功信息、积分到账信息,给司机发送出车成功信息、乘客到达信息, 给后台管理员发送预警信息、待办信息等,而消息又分为推送消息、短信消息、邮件消息等等。这些不同的场景以及不同的消息类型组合起来,种类非常的多,如果每一种都单独开发,则比较耗时,且代码相当凌乱。于是,我们在消息中心模块主要采用策略模式解决这个问题。首先,定义消息处理抽象类AbstractMessageHandleStratege,在里面定义了消息处理发送的模板(模板模式),以及相关子类需要实现的抽象方法,如查询接受者列表、定制消息模板,合并消息内容、记录消息地址等; 不同的消息类型子类继承抽象类,标注自己属于哪种消息类型,以及实现抽象类中的其他抽象方法。然后定义消息发送门面类MessageCentreFacade(门面模式),本类装载了所有消息类型对应的处理策略, 并且统一对外提供消息的异步或同步发送接口。 这样,本系统在发送消息的地方只需要组装好原始消息的相关纤细,然后调用消息门面类的发送消息即可完成消息的发送。当需要新增新的消息类型的时候,只需要继承消息处理抽象类编写新的消息类型子类,标注自身的消息类型即可。
** 二 、建造者模式让创建消息更加的简单**
如上所述,发送消息的地方需要装载好消息的原始信息,但是因为消息的多样性,导致这样的原始的信息相当的复杂,需要包含消息的类型:消息的接收人,可能是客户,可能是限定范围,可能是某个具体的人(这样的查询逻辑我们放在上述策略的子类中实现);发送的方式:邮件方式、app推送、短信通知等;消息内容的模板,中文消息、英文消息等等。消息的原始信息中既包含不变的基本信息,又包含不确定的可变信息,这样就导致了手动创建消息原始信息非常困难。于是,我们在这里采用建造者模式,解决原始消息的创建问题。首先,定义一个OriginMessageBuilder,以及一个返回OriginMessageModel对象的init接口。其中OriginMessageModel为Builder的内部类,它包含了原始信息的全部内容,隐藏了创建对象的细节,它的把一个创建零件的方法都返回自身,方便链式调用。在这个对象中,我们提供了通用必要信息的检测和非必要信息的解析,保证最终生成的是可用的原始消息。 这样我们在需要生成原始消息的地方,只要传入必要的信息,然后根据常见不同,决定是否携带其他信息,比如给深圳区的某类用户推送某个新的活动的时候,只需要携带活动内容,然后指定消息为APP推送消息,推送区域为深圳,推送对象为某类用户即可,而不需要携带邮件等其他信息。 如此,我们的原始消息建造者模式就达到了提供基本消息内容不变,其他组合动态改变的目标。
三、责任链模式在订单结算中的使用
由于是新项目的推广,我们的新能源网约车,在上线伊始出的活动类型非常的多,因此在订单结算的时候涉及多个活动的优惠方式的计算。在这里我们通过使用责任链模式,很好的规划了订单优惠的结算方式。首先定义了一个优惠抽象类AbstractDiscount,定义了参与资格、优惠计算、优惠优先级,优惠是否可以叠加,以及叠加方式等抽象方法。然后定义了DiscountChain类持有了全部优惠抽象类的字类(具体的优惠类型),并且按照优先级别进行排序。在订单结算的时候,传入订单具体信息,通过DiscountChain,有最高优先级的优惠类型开始调用,直到调用到不能叠加或全部链调用完毕为止。比如一个新用户,即满足新用户满减,又满足某促销打折活动,则可叠加优惠,用力与营销部门对新用户的推广。
整个新能源网约车项目的开发,包括交通部要求的数据上报,以及最终申请下来网约车牌照资质历时11个月,于2021年2月全部完成。网约车项目首先在广东省的某市以及安徽省某市上线,投放,到目前为止,项目运行稳定,用户量规模尚可,客户评价满意度较高,尤其是客户端和车载大屏端的联动,获得了大多数用户的好评。其中是活动系统,不但满足了公司运营部的部分复杂活动动态组合过滤掉要求,也达到了拓展用户,提升了用户满意度。
实践证明,。。。。。
但是,在开发的过程中也存在了一些不足之处,首先就是在软件开发之初对于交通部要求的网约车数据上报的要求细节了解不足,不知道数据上报需要在特点的VPN下进行。导致后来新增了特定的数据上报服务器专门用于数据上传,花费了一定的时间。所幸我们在开发中都把上传数据发布到kafka中,只需上句上报服务重新部署,订阅上报数据即可,没有造成太大的时间成本的浪费。另外就是,开发的前期阶段,我们把订单的实时轨轨坐标迹存储在了hbase中,但是后期考虑到数据不但上报到了交通部,在集成高德猎鹰轨迹API的时候,已经帮我们做了存储,这样的坐标信息本地再次存储意义不大,就取消了这样的存储,但是也消耗了部分人力与实践成本。这两点就告诉我,在以后的项目架构设计之前,应该做更清楚的细节需求挖掘,更多的资源投入权衡。