设计模式在外卖营销业务中的实践

随着美团外卖业务的不断迭代与发展,外卖用户数量也在高速地增长。在这个过程中,外卖营销发挥了“中流砥柱”的作用,因为用户的快速增长离不开高效的营销策略。而由于市场环境和业务环境的多变,营销策略往往是复杂多变的,营销技术团队作为营销业务的支持部门,就需要快速高效地响应营销策略变更带来的需求变动。因此,设计并实现易于扩展和维护的营销系统,是美团外卖营销技术团队不懈追求的目标和必修的基本功。

本文通过自顶向下的方式,来介绍设计模式如何帮助我们构建一套易扩展、易维护的营销系统。本文会首先介绍设计模式与领域驱动设计(Domain-DrivenDesign,以下简称为DDD)之间的关系,然后再阐述外卖营销业务引入业务中用到的设计模式以及其具体实践案例。

同时,我们也需要在代码工程中贯彻和实现领域模型。因为代码工程是领域模型在工程实践中的直观体现,也是领域模型在技术层面的直接表述。而设计模式,可以说是连接领域模型与代码工程的一座桥梁,它能有效地解决从领域模型到代码工程的转化。

所谓“模式”,就是一套反复被人使用或验证过的方法论。从抽象或者更宏观的角度上看,只要符合使用场景并且能解决实际问题,模式应该既可以应用在DDD中,也可以应用在设计模式中。事实上,Evans也是这么做的。他在著作中阐述了Strategy和Composite这两个传统的GOF设计模式是如何来解决领域模型建设的。因此,当领域模型需要转化为代码工程时,同构的模式,天然能够将领域模型翻译成代码模型。

营销业务的特点

如前文所述,营销业务与交易等其他模式相对稳定的业务的区别在于,营销需求会随着市场、用户、环境的不断变化而进行调整。也正是因此,外卖营销技术团队选择了DDD进行领域建模,并在适用的场景下,用设计模式在代码工程的层面上实践和反映了领域模型。以此来做到在支持业务变化的同时,让领域和代码模型健康演进,避免模型腐化。

理解设计模式

软件设计模式(Designpattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码,让代码更容易被他人理解,保证代码可靠性,程序的重用性。可以理解为:“世上本来没有设计模式,用的人多了,便总结出了一套设计模式。”

设计模式原则

面向对象的设计模式有七大基本原则:

简单理解就是:开闭原则是总纲,它指导我们要对扩展开放,对修改关闭;单一职责原则指导我们实现类要职责单一;里氏替换原则指导我们不要破坏继承体系;依赖倒置原则指导我们要面向接口编程;接口隔离原则指导我们在设计接口的时候要精简单一;迪米特法则指导我们要降低耦合。

设计模式就是通过这七个原则,来指导我们如何做一个好的设计。但是设计模式不是一套“奇技淫巧”,它是一套方法论,一种高内聚、低耦合的设计思想。我们可以在此基础上自由的发挥,甚至设计出自己的一套设计模式。

当然,学习设计模式或者是在工程中实践设计模式,必须深入到某一个特定的业务场景中去,再结合对业务场景的理解和领域模型的建立,才能体会到设计模式思想的精髓。如果脱离具体的业务逻辑去学习或者使用设计模式,那是极其空洞的。接下来我们将通过外卖营销业务的实践,来探讨如何用设计模式来实现可重用、易维护的代码。

3.2.1业务简介

“邀请下单”是美团外卖用户邀请其他用户下单后给予奖励的平台。即用户A邀请用户B,并且用户B在美团下单后,给予用户A一定的现金奖励(以下简称返奖)。同时为了协调成本与收益的关系,返奖会有多个计算策略。邀请下单后台主要涉及两个技术要点:

3.2.2返奖规则与设计模式实践

业务建模

如图是返奖规则计算的业务逻辑视图:

从这份业务逻辑图中可以看到返奖金额计算的规则。首先要根据用户状态确定用户是否满足返奖条件。如果满足返奖条件,则继续判断当前用户属于新用户还是老用户,从而给予不同的奖励方案。一共涉及以下几种不同的奖励方案:

新用户

老用户

计算完奖励金额以后,还需要更新用户的奖金信息,以及通知结算服务对用户的金额进行结算。这两个模块对于所有的奖励来说都是一样的。

可以看到,无论是何种用户,对于整体返奖流程是不变的,唯一变化的是返奖规则。此处,我们可参考开闭原则,对于返奖流程保持封闭,对于可能扩展的返奖规则进行开放。我们将返奖规则抽象为返奖策略,即针对不同用户类型的不同返奖方案,我们视为不同的返奖策略,不同的返奖策略会产生不同的返奖金额结果。

在我们的领域模型里,返奖策略是一个值对象,我们通过工厂的方式生产针对不同用户的奖励策略值对象。下文我们将介绍以上领域模型的工程实现,即工厂模式和策略模式的实际应用。

模式:工厂模式

工厂模式又细分为工厂方法模式和抽象工厂模式,本文主要介绍工厂方法模式。

模式定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法是一个类的实例化延迟到其子类。

工厂模式通用类图如下:

我们通过一段较为通用的代码来解释如何使用工厂模式:

//抽象的产品publicabstractclassProduct{publicabstractvoidmethod();}//定义一个具体的产品(可以定义多个具体的产品)classProductAextendsProduct{@Overridepublicvoidmethod(){}//具体的执行逻辑}//抽象的工厂abstractclassFactory{abstractProductcreateProduct(Classc);}//具体的工厂可以生产出相应的产品classFactoryAextendsFactory{@OverrideProductcreateProduct(Classc){Productproduct=(Product)Class.forName(c.getName()).newInstance();returnproduct;}}模式:策略模式

模式定义:定义一系列算法,将每个算法都封装起来,并且它们可以互换。策略模式是一种对象行为模式。

策略模式通用类图如下:

我们通过一段比较通用的代码来解释怎么使用策略模式:

//定义一个策略接口publicinterfaceStrategy{voidstrategyImplementation();}//具体的策略实现(可以定义多个具体的策略实现)publicclassStrategyAimplementsStrategy{@OverridepublicvoidstrategyImplementation(){System.out.println("正在执行策略A");}}//封装策略,屏蔽高层模块对策略、算法的直接访问,屏蔽可能存在的策略变化publicclassContext{privateStrategystrategy=null;publicContext(Strategystrategy){this.strategy=strategy;}publicvoiddoStrategy(){strategy.strategyImplementation();}}工程实践

通过上文介绍的返奖业务模型,我们可以看到返奖的主流程就是选择不同的返奖策略的过程,每个返奖策略都包括返奖金额计算、更新用户奖金信息、以及结算这三个步骤。我们可以使用工厂模式生产出不同的策略,同时使用策略模式来进行不同的策略执行。首先确定我们需要生成出n种不同的返奖策略,其编码如下:

//抽象策略publicabstractclassRewardStrategy{publicabstractvoidreward(longuserId);publicvoidinsertRewardAndSettlement(longuserId,intreward){};//更新用户信息以及结算}//新用户返奖具体策略ApublicclassnewUserRewardStrategyAextendsRewardStrategy{@Overridepublicvoidreward(longuserId){}//具体的计算逻辑,...}//老用户返奖具体策略ApublicclassOldUserRewardStrategyAextendsRewardStrategy{@Overridepublicvoidreward(longuserId){}//具体的计算逻辑,...}//抽象工厂publicabstractclassStrategyFactory{abstractRewardStrategycreateStrategy(Classc);}//具体工厂创建具体的策略publicclassFactorRewardStrategyFactoryextendsStrategyFactory{@OverrideRewardStrategycreateStrategy(Classc){RewardStrategyproduct=null;try{product=(RewardStrategy)Class.forName(c.getName()).newInstance();}catch(Exceptione){}returnproduct;}}通过工厂模式生产出具体的策略之后,根据我们之前的介绍,很容易就可以想到使用策略模式来执行我们的策略。具体代码如下:

publicclassRewardContext{privateRewardStrategystrategy;publicRewardContext(RewardStrategystrategy){this.strategy=strategy;}publicvoiddoStrategy(longuserId){intrewardMoney=strategy.reward(userId);insertRewardAndSettlement(longuserId,intreward){insertReward(userId,rewardMoney);settlement(userId);}}}接下来我们将工厂模式和策略模式结合在一起,就完成了整个返奖的过程:

publicclassInviteRewardImpl{//返奖主流程publicvoidsendReward(longuserId){FactorRewardStrategyFactorystrategyFactory=newFactorRewardStrategyFactory();//创建工厂Inviteeinvitee=getInviteeByUserId(userId);//根据用户id查询用户信息if(invitee.userType==UserTypeEnum.NEW_USER){//新用户返奖策略NewUserBasicRewardnewUserBasicReward=(NewUserBasicReward)strategyFactory.createStrategy(NewUserBasicReward.class);RewardContextrewardContext=newRewardContext(newUserBasicReward);rewardContext.doStrategy(userId);//执行返奖策略}if(invitee.userType==UserTypeEnum.OLD_USER){}//老用户返奖策略,...}}工厂方法模式帮助我们直接产生一个具体的策略对象,策略模式帮助我们保证这些策略对象可以自由地切换而不需要改动其他逻辑,从而达到解耦的目的。通过这两个模式的组合,当我们系统需要增加一种返奖策略时,只需要实现RewardStrategy接口即可,无需考虑其他的改动。当我们需要改变策略时,只要修改策略的类名即可。不仅增强了系统的可扩展性,避免了大量的条件判断,而且从真正意义上达到了高内聚、低耦合的目的。

3.2.3返奖流程与设计模式实践

当受邀人在接受邀请人的邀请并且下单后,返奖后台接收到受邀人的下单记录,此时邀请人也进入返奖流程。首先我们订阅用户订单消息并对订单进行返奖规则校验。例如,是否使用红包下单,是否在红包有效期内下单,订单是否满足一定的优惠金额等等条件。当满足这些条件以后,我们将订单信息放入延迟队列中进行后续处理。经过T+N天之后处理该延迟消息,判断用户是否对该订单进行了退款,如果未退款,对用户进行返奖。若返奖失败,后台还有返奖补偿流程,再次进行返奖。其流程如下图所示:

我们对上述业务流程进行领域建模:

可以看到,我们通过建模将返奖流程的多个步骤映射为系统的状态。对于系统状态的表述,DDD中常用到的概念是领域事件,另外也提及过事件溯源的实践方案。当然,在设计模式中,也有一种能够表述系统状态的代码模型,那就是状态模式。在邀请下单系统中,我们的主要流程是返奖。对于返奖,每一个状态要进行的动作和操作都是不同的。因此,使用状态模式,能够帮助我们对系统状态以及状态间的流转进行统一的管理和扩展。

模式:状态模式

模式定义:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。

状态模式的通用类图如下图所示:

对比策略模式的类型会发现和状态模式的类图很类似,但实际上有很大的区别,具体体现在concreteclass上。策略模式通过Context产生唯一一个ConcreteStrategy作用于代码中,而状态模式则是通过context组织多个ConcreteState形成一个状态转换图来实现业务逻辑。接下来,我们通过一段通用代码来解释怎么使用状态模式:

通过前文对状态模式的简介,我们可以看到当状态之间的转换在不是非常复杂的情况下,通用的状态模式存在大量的与状态无关的动作从而产生大量的无用代码。在我们的实践中,一个状态的下游不会涉及特别多的状态装换,所以我们简化了状态模式。当前的状态只负责当前状态要处理的事情,状态的流转则由第三方类负责。其实践代码如下:

3.3.1业务简介

继续举例,点评App的外卖频道中会预留多个资源位为营销使用,向用户展示一些比较精品美味的外卖食品,为了增加用户点外卖的意向。当用户点击点评首页的“美团外卖”入口时,资源位开始加载,会通过一些规则来筛选出合适的展示Banner。

3.3.2设计模式实践

对于投放业务,就是要在这些资源位中展示符合当前用户的资源。其流程如下图所示:

从流程中我们可以看到,首先运营人员会配置需要展示的资源,以及对资源进行过滤的规则。我们资源的过滤规则相对灵活多变,这里体现为三点:

为了实现过滤规则的解耦,对单个规则值对象的修改封闭,并对规则集合组成的过滤链条开放,我们在资源位过滤的领域服务中引入了责任链模式。

模式:责任链模式

模式定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。

责任链模式通用类图如下:

我们通过一段比较通用的代码来解释如何使用责任链模式:

下面通过代码向大家展示如何实现这一套流程:

本文从营销业务出发,介绍了领域模型到代码工程之间的转化,从DDD引出了设计模式,详细介绍了工厂方法模式、策略模式、责任链模式以及状态模式这四种模式在营销业务中的具体实现。除了这四种模式以外,我们的代码工程中还大量使用了代理模式、单例模式、适配器模式等等,例如在我们对DDD防腐层的实现就使用了适配器模式,通过适配器模式屏蔽了业务逻辑与第三方服务的交互。因篇幅原因不再进行过多的阐述。

对于营销业务来说,业务策略多变导致需求多变是我们面临的主要问题。如何应对复杂多变的需求,是我们提炼领域模型和实现代码模型时必须要考虑的内容。DDD以及设计模式提供了一套相对完整的方法论帮助我们完成了领域建模及工程实现。其实,设计模式就像一面镜子,将领域模型映射到代码模型中,切实地提高代码的复用性、可扩展性,也提高了系统的可维护性。

当然,设计模式只是软件开发领域内多年来的经验总结,任何一个或简单或复杂的设计模式都会遵循上述的七大设计原则,只要大家真正理解了七大设计原则,设计模式对我们来说应该就不再是一件难事。但是,使用设计模式也不是要求我们循规蹈矩,只要我们的代码模型设计遵循了上述的七大原则,我们会发现原来我们的设计中就已经使用了某种设计模式。

吴亮亮,2017年加入美团外卖,美团外卖营销后台团队开发工程师。

THE END
1.营销的定义与概念营销的概念营销(Marketing)是指企业通过一系列的活动、策略和方法,识别、创造和满足客户需求,从而实现企业目标的过程。营销不仅仅是销售产品或服务,还包括市场调研、产品开发、定价策略、促销活动、分销渠道管理以及售后服务等多个方面。 营销的主要目标 识别和满足客户需求:通过市场调研和分析,了解客户的需求和偏好,开发满足这些需求https://blog.csdn.net/u014745465/article/details/140176643
2.营销方案怎么做?这几个技巧帮你提升业绩!4. 营销团队培训:加强营销团队的培训,提高他们的业务素质和沟通能力。 5. 营销数据分析:定期分析营销数据,找出问题所在,优化营销方案。 总之,制定营销方案要紧紧围绕目标客户,精准定位,塑造品牌形象,制定合适的营销策略。同时,运用各种技巧提升业绩,为企业的长远发展奠定基础。在实践中不断总结经验,不断创新,才能在市场http://news.xnnews.com.cn/taoyitui/Article-xiaoxiaoYi-371.html
3.市场营销专业学生毕业后能从事市调人员、营销业务员、新媒体运营专员、网店运营专员、品牌策划专员等;职业提升岗位:经理助理、营销经理、新媒体运营经理、网店店长、品牌经理、职业经理人、创业者等。 专业介绍 本专业旨在培养拥护党的基本路线,具备良好的职业道德和敬业精神,适应社会主义生产服务第一线需要,德、智、体、美、劳等方https://www.ynctv.edu.cn/jjglxy/zyjs/scyxzy.htm
4.新业务营销(精选十篇)移动新业务之所以得到快速的发展离不开运营商对移动新业务多种方式的营销组合, 组合方式多种多样, 通过对营销组合的因素进行分析之后, 组合方式大致可以分为:资费套餐的组合、服务产品的组合、同业竞争者之间的组合等多种创新方式。进而通过对影响营销组合的市场因素进行分析, 制定营销组合的方式。 https://www.360wenmi.com/f/cnkeyc2q20el.html
5.汽车技术服务与营销文理兼收本专业学生除在校内学习汽车有关理论知识外,还将在校企结合的实训基地进行实习实践和顶岗实训,将学生培养成掌握汽车基本知识和技能、熟悉营销业务,既能从事汽车技术服务,又能担当汽车营销骨干的应用性专门人才。本专业学生通过学习及考核,可获得计算机等级证书、英语应用能力考试(A级或B级)证书,汽车维修中级或高级职业证书https://zb.xasyu.cn/2015cz/zyjs10.html
6.新业务营销范文12篇(全文)新业务营销 第1篇 1 联通与中国移动的营销策略比较 1.1 营销对象 所有的营销策略都是以营销对象为基础,营销对象涵盖三个方面的内容,即企业目标、企业财务目标和企业市场目标。现阶段,中国移动的主要营销目标特点是:以守为主,兼吸纳中低端市场;中国联通则是以攻为主,通过各种营销策略不断扩大用户市场份额和收入市场https://www.99xueshu.com/w/ikey2ixsh5wr.html
7.智度股份业务介绍发现大多数投资者不理解智度股份的业务,在这儿发现大多数投资者不理解智度股份的业务,在这儿转发一下17年报后的投资者交流会内容,介绍得比较详细。 一、公司董事会秘书李凌霄女士介绍公司业务情况 (一)公司业务情况$智度股份(SZ000676)$ 智度股份是一家技术驱动型的国际化公司,公司主营业务为互联网媒体业务和数字营销业务,两大核心业务板块两翼齐飞。公司员工约700https://xueqiu.com/9258718599/127462883
8.业务销售岗位职责15篇业务销售岗位职责4 1、认真贯彻执行集团总公司销售管理规定和实施细则,努力提高自身营销业务水平,产品学问水平,道德修养水平。 2、把握所属辖区的市场动态和进展趋势,依据市场变动规律,提出实在的区域营销计划方案,以及个人的营销工作流程和细则。 3、扩大所辖地区的销售网络,谙习本区域的市场特点、营销特点,与本区域大https://www.yjbys.com/hr/gangwei/4141976.html
9.营销年终工作总结(通用15篇)在工作中我也非常重视学习作为一名营销业务员的业务知识(专业技术知识、心理学),坚持一边工作一边学习。用正确的世界观、人生观、价值观指导自己的工作和学习,结合自己在工作实践中学习到的如何处理和解决事物的能力,不断提高自己。首先是向领导学。半年来,虽与我领导办事的时间不多,但我亲身感受到了领导风范,使我受https://www.jy135.com/nianzhongzongjie/1491879.html
10.国网(营销1)95统一标准、统一运作、集中管控,统一市县营销业务管理模式,实现地(市)公司、县公司营销核心环节和重点业务的协同化运作。本通则适用于公司总部(分部)及所属各级单位的营销管理工作。公司各级控股、参股单位营销管理工作参照执行。第二章 机构与职责第一节 机构设置 公司总部层面设营销部和国网客户服务中心。中国电科院(https://max.book118.com/html/2017/0321/96313375.shtm
11.集团营销?业务通集团营销?业务通(SaaS软件)一站式业务营销及客户关系管理系统平台。接单制胜,赢在跟单!让您轻松找到客户,100%提高您的业务签单率!!http://win.madeinchina.cn/
12.营销会议上的讲话稿(通用12篇)第三,这是一个业务能力比拼的舞台。在这里充满着竞争,这要求我们在学习当中不断提高自己的营销业务能力,明白团结协助团队精神的重要性;这里也是我们将理论知识付诸于实践的平台,它更好地帮助我们处理好理论与实践的关系。我们要感谢联通为我们提供了这样一个平台,因为它我们的生活将变得丰富多彩。https://m.ruiwen.com/gongwen/huiyijianghua/1135665.html
13.追过程之追业务工具营销业务追踪CRM模块 2、解读 在营销体系CRM模块中,CRM系统作为业绩追踪的载体,从客户分配规则到客户成熟度的分类,到不同客户的跟进周期,到客户跟踪的过程记录,到管理报表提炼,都是销售业务中追业绩的工具。 在销售团队管理中,心态大于工作习惯大于流程大于技能大于工具,心态、习惯、流程、技能、工具都是管理业务的工具https://www.jianshu.com/p/d8db09350ed4