当前位置: 首页 > 后端技术 > Node.js

关于产品推广码的优雅

时间:2023-04-03 11:41:34 Node.js

背景介绍据我了解,几乎所有的互联网公司都有电子商务相关的项目,而且大部分还在起着举足轻重的作用,比如京东、淘宝。既然有了电商项目,就不可避免地涉及到产品。一旦有产品,就会有各种促销活动,比如满100立减20,3月8日妇女节立减10等类似活动。作为coder,如何在实现产品狗的要求下,用最少的代码改动实现最优雅的实现。今日菜菜不够好,出丑了D妹。下面以.netCorec#代码为例,其他语言类似。D妹版首先,D妹有一个商品对象,商品中有价格属性,价格单位分为classProduct{//其他属性省略publicintPrice{get;放;}}下面有一个完整的100减20的活动,结算价格时代码是这样的publicintGetPrice(){Productp=newProduct();intret=p.Price;if(p.Price>=100*100){ret=ret-20*100;返回ret;}问题?按照要求,没有问题,计算出来的结果也是正确的。但是从程序艺术的角度来看,其实是非常丑陋的。现在整个网站还有另一个10%的折扣活动。刚好一个产品参加了以上两个活动,也可以结合使用(假设参加活动的顺序是先打折再满减)。这时D妹的代码就变成了这样publicintGetPrice(){Productp=newProduct();//10%折扣事件intret=p.Price*90/100;//全折扣事件if(ret>=100*100){ret=ret-20*100;返回ret;}如果现在再有类似事件,需要修改这段代码,严重违反了开放封闭原则,频繁修改已经上线的代码。出现bug的概率会大大增加。这也是D姐leader骂她,让她codereview的原因。如何优化优化版?在修改代码之前,还是要提醒一下,有几点需要注意:商品最好有一个通用的基类,这样所有的商品都有一个控制点,一个入口留给以后统一添加属性。就像一个网关系统,为什么要诞生网关组件呢?因为有了它,我们可以方便的添加认证、授权、统计等一系列行为。任何促销活动最好有一个基类,它的作用类似于商品基类。对于商品来说,任何促销活动都是商品行为的改变,影响最终的商品价格,所以获取价格的行为需要特殊处理。不同类型的促销应该能够在不影响其他类型促销的情况下自行扩展。不同类型的促销活动可以叠加使用(其实这就涉及到每次活动的计算标准是商品原价还是促销后的价格的问题)。基于以上几点,首先做商品抽象对象//商品抽象基类abstractclassBaseProduct{//商品价格,单位:分publicintPrice{get;放;}//获取商品价格抽象方法publicabstractintGetPrice();}//抽象商品(如话费商品),继承商品基类classVirtualProduct:BaseProduct{publicoverrideintGetPrice(){returnthis.Price;}}下Activity的基类也需要抽象//各种Activity的抽象基类,继承要封装的类型的基类abstractclassBaseActivity:BaseProduct{}有同学会问,为什么要继承base这里的商品等级?主要是因为activity的基类可以嵌套使用,这样我就可以同时实现多个activity。不懂没关系,再往下看带着这道题实现一个打折活动//打折活动基类支持两种商品同时进行多次结算classDiscountActivity:BaseActivity{BaseProduct产品=空;publicDiscountActivity(intdiscount,BaseProduct_product){Discount=discount;产品=_产品;}//折扣,比如90%off就是90%publicintDiscount{get;放;}//获取折扣后的价格publicoverrideintGetPrice(){returnproduct.GetPrice()*Discount/100;}}实现一个全减活动,支持自定义全减条件classReductionActivity:BaseActivity{BaseProductproduct=null;//全减对应表DictionaryreductMap=null;publicReductionActivity(Dictionary_redutMap,BaseProduct_product){reductMap=_redutMap;产品=_产品;}//获取折扣后的价格publicoverrideintGetPrice(){varproductAmount=product.GetPrice();//根据商品总价获取价格降价后的价格varreductValue=reductMap.OrderByDescending(s=>s.Key).FirstOrDefault(s=>productAmount>=s.Key).Value;返回productAmount-reductValue;}}现在让我们为产品VirtualProductp=newVirtualProduct(){Price=1000};做一个促销。//折扣活动DiscountActivityda=newDiscountActivity(90,p);varretPrice=da.GetPrice();Console.WriteLine($"折扣价{retPrice}");//也可以叠加参与满减活动Dictionarym=newDictionary();m.Add(200,5);//5减5满200m.Add(300,10);m.Add(500,20);m.Add(1000,50);//这个活动可以使用ReductionActivityra=newReductionActivity(m,da);retPrice=ra.GetPrice();Console.WriteLine($"全额折扣后的价格{retPrice}");ReductionActivityra2=newReductionActivity(m,ra);retPrice=ra2.GetPrice();Console.WriteLine($"进一步折扣后的价格{retPrice}");输出结果:满折后价格900,满折后价格880,满折后价格860。现在终于可以更加优雅的进行商品的满折和打折活动了。它已经发展到可以同时推广多种产品。以上代码可以比较优雅,可以针对单品进行促销活动,但现实往往很骨感。在真实电商场景中,多产品结算是主要关注点。同样的想法如何实现呢?由于本次需要实现的是多商品促销结算,所以需要自定义商品列表作为结算对象该对象的行为层类似于单品,有一个需求变化点的抽象:获取价格//商品列表的基类,用于活动结算。UseclassActivityListProduct:List{//商品列表活动结算方法,基类必须重写publicvirtualintGetPrice(){intret=0;base.ForEach(s=>{ret+=s.GetPrice();});返还;它被抽象出来用于继承不同的促销活动。这里需要继承ActivityListProduct。为什么?类似于单个商品,为了实现多个子类的嵌套调用//商品列表活动的基类,继承自商品列表基类内部抽象类BaseActivityList:ActivityListProduct{}创建打折和全打折活动//折扣活动基类,支持多个商品同时结算classDiscountActivityList:BaseActivityList{ActivityListProductproduct=null;publicDiscountActivityList(int折扣,ActivityListProduct_product){折扣=折扣;产品=_产品;}//折扣,比如90%off就是90%publicintDiscount{get;放;}publicoverrideintGetPrice(){varproductPrice=product.GetPrice();退货价格*折扣/100;}}//完全还原活动类ReductionActivityList:BaseActivityList{ActivityListProductproduct=null;//全减对应表DictionaryreductMap=null;publicReductionActivityList(Dictionary_redutMap,ActivityListProduct_product){reductMap=_redutMap;产品=_产品;}//获取折扣后的价格publicoverrideintGetPrice(){varproductAmount=product.GetPrice();//根据商品的总价得到要减价的价格varreductValue=reductMap.OrderByDescending(s=>s.Key).FirstOrDefault(s=>productAmount>=s.Key).Value;返回productAmount-reductValue;}}先来一波多品促销VirtualProductp=newVirtualProduct(){Price=1000};VirtualProductp2=newVirtualProduct(){Price=1000};ActivityListProductlst=newActivityList产品();lst.Add(p);lst.Add(p2);DiscountActivityListdalist=newDiscountActivityList(80,lst);Console.WriteLine($"折扣后价格{dalist.GetPrice()}");DiscountActivityListdalist2=newDiscountActivityList(90,dalist);Console.WriteLine($"折扣后价格{dalist2.GetPrice()}");DiscountActivityListdalist3=newDiscountActivityList(90,dalist2);Console.WriteLine($"打折后的价格{dalist3.GetPrice()}");//也可以叠加参与满减活动Dictionarym=newDictionary();m.Add(200,5);//满200减去5m.Add(300,10);m.Add(500,20);m.Add(1000,50);ReductionActivityListral=newReductionActivityList(m,dalist3);优惠价{ral.GetPrice()}");结算结果:优惠价1600优惠价1440优惠价1296满减后优惠价1246现在基本可以防止D妹被打了骂神化版,看留言区,知道D妹为什么叫D妹吗?领取建筑师进阶数据大礼包