临汾山东漯河饰品美体美文
投稿投诉
美文创意
爱情通信
用品婚姻
爱好看病
美体软件
影音星座
瑜伽周边
星座办公
饰品塑形
搞笑减肥
幼儿两性
智家潮品
漯河衢州
兴义眉山
桂林阳泉
玉溪简阳
山东遂宁
永城新余
梧州洛阳
泸州温州
临汾清远
营口常熟
浙江大连
桐乡宜昌

StrategyPattern教你秒变神枪手

3月19日 倾城傷投稿
  作者:若采
  作者案:本文介绍的是StrategyPattern(策略模式)。干货满满,希望阅读后你能有所收获目的
  做一件事情有不同的实现方式,可以将变化的部分和不变的部分剥离开,去除大量的ifelse,提供高扩展性。例子代码
  比如我们想要带妹吃鸡,就要成为一个神枪手。在各种枪战游戏中,有各种不同的枪,我们要根据射程的不同选择不同的枪进行射击。
  如果枪的子弹数量都不富裕,我们要用最少的子弹,最合适的方法达到最强伤害,最终大吉大利。
  当我们距离对手:1米以内,使用平底锅(想我当时三级头三级甲,手持AKM,满血满状态,三级包里药包无数,到了决赛圈被平底锅堵在墙角打死啦);100米左右,使用冲锋枪;超过1000米,使用狙击枪(对于我这样的小菜鸡,基本流程是开一枪没打中,暴露位置,被别人一狙打死。。。囧)。面条式代码判断最强武器publicclassNoodlesKillProcessor{根据距离判断最好的武器击杀对手paramdistanceBadSmellpublicstaticvoidkillByDistance(intdistance){if(distance0){thrownewRuntimeException(距离咋还能是负数呢?);}if(distance0distance1){System。out。println(发现敌人);System。out。println(两步快速走过去);System。out。println(掏出平底锅呼他);}if(distance1distance10){System。out。println(发现敌人);System。out。println(快速走过去);System。out。println(掏出手枪打他);}if(distance10distance100){System。out。println(发现敌人);System。out。println(身体站直,心态稳住);System。out。println(掏出冲锋枪打他);}if(distance100distance1000){System。out。println(发现敌人);System。out。println(身体蹲下降低后坐力);System。out。println(掏出步枪);System。out。println(打开3倍镜);System。out。println(开枪射击);}if(distance1000){System。out。println(发现敌人);System。out。println(趴在草丛里苟着);System。out。println(掏出狙击枪);System。out。println(打开8倍镜);System。out。println(开枪射击);}}}问题分析
  我觉得这有3个问题,具体分析如下:
  01可读性问题
  我看这么多ifelse语句,里面的sout语句目前三四行也还好,如果我们有上百行的语句,里面也有很多ifelse,这样都不知道下个主if跑哪去啦
  02重复性问题
  全都需要发现敌人,如果发现敌人是个成百上千行代码,就很麻烦啦。
  03可维护性问题
  如果这时候我们新增了一种枪,比如是霰弹枪,适用10到20的时候使用,这时候我们就需要在加一个if语句如下:面条式代码判断最强武器publicclassNoodlesKillProcessor{根据距离判断最好的武器击杀对手paramdistanceBadSmellpublicstaticvoidkillByDistance(intdistance){if(distance0){thrownewRuntimeException(距离咋还能是负数呢?);}if(distance0distance1){System。out。println(发现敌人);System。out。println(两步快速走过去);System。out。println(掏出平底锅呼他);}if(distance1distance10){System。out。println(发现敌人);System。out。println(快速走过去);System。out。println(掏出手枪打他);}if(distance10distance20){System。out。println(发现敌人);System。out。println(身体站直,瞄准);System。out。println(打一枪算一枪);}if(distance20distance100){System。out。println(发现敌人);System。out。println(身体站直,心态稳住);System。out。println(掏出冲锋枪打他);}if(distance100distance1000){System。out。println(发现敌人);System。out。println(身体蹲下降低后坐力);System。out。println(掏出步枪);System。out。println(打开3倍镜);System。out。println(开枪射击);}if(distance1000){System。out。println(发现敌人);System。out。println(趴在草丛里苟着);System。out。println(掏出狙击枪);System。out。println(打开8倍镜);System。out。println(开枪射击);}}}
  这个看着也没啥大问题的样子,不就是加了个if么,但是由于我们改动了这个文件,测试同学问我们需要测试哪些功能,说是测一种枪需要5天
  问题来啦,本来说是你增加一种枪,需要测5天,但是现在你说改了这文件,上下可能有些局部变量共享的,或者有些方法可能改了入参的值,这些有负作用的方法被调用啦,所以可能狙击枪也得测一测,可能手枪也得测一测。
  测试同学崩了,本来5天的工作量,搞成了56天,一个月都在测枪
  初步尝试解决
  我们先定义好一个基础类,解决一下可读性问题和重复性问题。
  定义一个基础武器类:抽象的枪publicabstractclassWeapon{发现敌人protectedvoidfindEnemy(){System。out。println(发现敌人);}开枪前的动作protectedabstractvoidpreAction();开枪protectedabstractvoidshoot();整体的动作publicvoidkill(){findEnemy();preAction();shoot();}}
  逐个实现武器的具体类、平底锅、冲锋枪、步枪等类如下:平底锅publicclassPanextendsWeapon{OverrideprotectedvoidpreAction(){System。out。println(两步快速走过去);}Overrideprotectedvoidshoot(){System。out。println(掏出平底锅呼他);}}手枪类publicclassPistolextendsWeapon{OverrideprotectedvoidpreAction(){System。out。println(快速走过去);}Overrideprotectedvoidshoot(){System。out。println(掏出手枪打他);}}霰弹枪publicclassShotgunextendsWeapon{OverrideprotectedvoidpreAction(){System。out。println(身体站直,瞄准);}Overrideprotectedvoidshoot(){System。out。println(打一枪算一枪);}}狙击枪publicclassSniperRifleextendsWeapon{OverrideprotectedvoidpreAction(){System。out。println(趴在草丛里苟着);System。out。println(掏出狙击枪);System。out。println(打开8倍镜);}Overrideprotectedvoidshoot(){System。out。println(开枪射击);}}冲锋枪publicclassSubmachineGunextendsWeapon{OverrideprotectedvoidpreAction(){System。out。println(身体站直,心态稳住);}Overrideprotectedvoidshoot(){System。out。println(掏出冲锋枪打他);}}
  我们的方法就可以改动得更清晰啦抽象出类代码判断最强武器publicclassWeaponKillProcessor{根据距离判断最好的武器击杀对手paramdistanceBadSmellpublicstaticvoidkillByDistance(intdistance){if(distance0){thrownewRuntimeException(距离咋还能是负数呢?);}Wif(distance0distance1){weaponnewPan();}elseif(distance1distance10){weaponnewPistol();}elseif(distance10distance20){weaponnewShotgun();}elseif(distance20distance100){weaponnewSubmachineGun();}elseif(distance100distance1000){weaponnewRifle();}elseif(distance1000){weaponnewSniperRifle();}weapon。kill();}}
  类图如下:
  使用策略模式
  上面的代码没有解决最根本的问题,也就是去除ifelse,所用的方法其实就是将ifelse转换为for,这样的代码后续添加枪就不需要再增加新的类型啦。
  我们先定义一个通用的策略模式接口如下:策略模式publicinterfaceStrategyTextendsAbstractStrategyRequest,RextendsAbstractStrategyResponse{执行策略paramrequestreturnRexecuteStrategy(Trequest);}
  入参和出参都是基本的抽象类:策略模式抽象入参publicabstractclassAbstractStrategyRequest{}策略模式抽象出参publicabstractclassAbstractStrategyResponse{}
  实现一个武器抽象类实现接口:publicabstractclassWeaponStrategyimplementsStrategyWeaponStrategyRequest,AbstractStrategyResponse{发现敌人protectedvoidfindEnemy(){System。out。println(发现敌人);}开枪前的动作protectedabstractvoidpreAction();开枪protectedabstractvoidshoot();获取距离范围returnprotectedabstractRangeIntegerqueryDistanceRange();整体的动作publicvoidkill(){findEnemy();preAction();shoot();}OverridepublicAbstractStrategyResponseexecuteStrategy(WeaponStrategyRequestrequest){System。out。println(距离敌人request。getDistance());kill();}}
  其中的Range类实现如下:范围类paramTDataAllArgsConstructorpublicclassRangeTextendsComparableT{privateTprivateTpublicRange(Tstart,Tend){this。this。}privatebooleanisIncludeSprivatebooleanisIncludeE判断是否在范围内paramtargetreturnpublicbooleaninRange(Ttarget){if(isIncludeStart){if(start。compareTo(target)0){}}else{if(start。compareTo(target)0){}}if(isIncludeEnd){if(end。compareTo(target)0){}}else{if(end。compareTo(target)0){}}}}
  依次实现这个抽象武器策略类:平底锅publicclassPanStrategyextendsWeaponStrategy{OverrideprotectedvoidpreAction(){System。out。println(二步快速走过去);}Overrideprotectedvoidshoot(){System。out。println(掏出平底锅呼他);}OverrideprotectedRangeIntegerqueryDistanceRange(){returnnewRange(0,1);}}手枪类publicclassPistolStrategyextendsWeaponStrategy{OverrideprotectedvoidpreAction(){System。out。println(快速走过去);}Overrideprotectedvoidshoot(){System。out。println(掏出手枪打他);}OverrideprotectedRangeIntegerqueryDistanceRange(){returnnewRange(1,10);}}步枪publicclassRifleStrategyextendsWeaponStrategy{OverrideprotectedvoidpreAction(){System。out。println(身体蹲下降低后坐力);System。out。println(掏出步枪);System。out。println(打开3倍镜);}Overrideprotectedvoidshoot(){System。out。println(开枪射击);}OverrideprotectedRangeIntegerqueryDistanceRange(){returnnewRange(100,1000);}}霰弹枪publicclassShotgunStrategyextendsWeaponStrategy{OverrideprotectedvoidpreAction(){System。out。println(身体站直,瞄准);}Overrideprotectedvoidshoot(){System。out。println(打一枪算一枪);}OverrideprotectedRangeIntegerqueryDistanceRange(){returnnewRange(10,20);}}狙击枪publicclassSniperRifleStrategyextendsWeaponStrategy{OverrideprotectedvoidpreAction(){System。out。println(趴在草丛里苟着);System。out。println(掏出狙击枪);System。out。println(打开8倍镜);}Overrideprotectedvoidshoot(){System。out。println(开枪射击);}OverrideprotectedRangeIntegerqueryDistanceRange(){returnnewRange(1000,Integer。MAXVALUE);}}冲锋枪publicclassSubmachineGunStrategyextendsWeaponStrategy{OverrideprotectedvoidpreAction(){System。out。println(身体站直,心态稳住);}Overrideprotectedvoidshoot(){System。out。println(掏出冲锋枪打他);}OverrideprotectedRangeIntegerqueryDistanceRange(){returnnewRange(20,100);}}
  定义一个上下文类来对入参进行路由:策略上下文,用来路由策略publicclassStrategyContext{publicstaticfinalListWeaponStrategyWEAPONSTRATEGYSnewArrayList();static{WEAPONSTRATEGYS。add(newPanStrategy());WEAPONSTRATEGYS。add(newPistolStrategy());WEAPONSTRATEGYS。add(newRifleStrategy());WEAPONSTRATEGYS。add(newShotgunStrategy());WEAPONSTRATEGYS。add(newSniperRifleStrategy());WEAPONSTRATEGYS。add(newSubmachineGunStrategy());}publicstaticvoidexecute(Integerdistance){WEAPONSTRATEGYS。stream()。filter((weaponStrategy{RangeIntegerintegerRangeweaponStrategy。queryDistanceRange();returnintegerRange。inRange(distance);}))。findAny()。get()。executeStrategy(newWeaponStrategyRequest(distance));}}
  最后在主方法里面调用就好啦:publicclassApp{publicstaticvoidmain(String〔〕args){StrategyContext。execute(89);}}
  结果如下:距离敌人89
  发现敌人
  身体站直,心态稳住
  掏出冲锋枪打他
  类图如下:
  加入我们
  我们来自字节跳动飞书商业应用研发部(LarkBusinessApplications),目前我们在北京、深圳、上海、武汉、杭州、成都、广州、三亚都设立了办公区域。我们关注的产品领域主要在企业经验管理软件上,包括飞书OKR、飞书绩效、飞书招聘、飞书人事等HCM领域系统,也包括飞书审批、OA、法务、财务、采购、差旅与报销等系统。
  点击链接,欢迎各位加入我们!
投诉 评论

历史上的今天万达退出中国足坛!1998年9月27日1998年4月27日,甲A霸主大连万达无缘足协杯决赛。王健林赛后宣布万达退出甲A,引爆了!那是一场载入史册的足协杯半决赛,在金州体育场,成就了辽小虎的初步锋芒,也成就了中……i512400F12600KFi712700F搭配RTX30最近有粉丝想要搭配一款七八千元的电脑主机,因为有大型游戏需求,显卡要求稍微高一些,想要用RTX3070,硬件不能太丐,主板尽量用华硕、微星一线品牌。针对粉丝的要求,推荐了四套配……夏天有3种茶可以多喝健康营养师茶茶饮很多台湾人都喜欢喝茶,茶的滋味丰富又有层次,还含有多种对身体好的营养成份,喝茶时也能让身心感到放松。有营养师就介绍了很适合夏天喝的3种茶,不仅可以让我们消……顶薪没了,迈尔斯布里奇斯被控家暴和虐童两项重罪洛杉矶郡地区检察院以家庭暴力重罪和虐待儿童罪名,正式起诉黄蜂受限自由球员迈尔斯布里奇斯。24岁的布里奇斯在6月30日因为暴力伤害亲密伴侣被拘捕,最终以家庭暴力罪记录在案,……记者湖人有兴趣交易得到比尔筹码或是威少的到期合同首轮签直播吧6月18日讯今天,TheRinger记者凯文奥康纳在一篇报道中提到湖人队今夏会有兴趣通过交易得到比尔。我最近听到的一个名字是布拉德利比尔,这是他们(湖人)想要得到的……有免费滑冰区!来八一湖等五处大众冰场体验冰上快乐玉渊潭公园南门向西,沿小路走不远,孩子们的欢声笑语由远及近。八一湖冰场上,小朋友们脚踩冰鞋往来穿梭,大人们三五成群打着冰球,充满老北京冬日记忆的亲子冰车一会儿滑到东一会儿滑到西……云原生从业者年薪200W,诱人的职业背后是什么?文张从祥编辑王小坤越来越多的企业开始拥抱云原生,云原生技术在制造、政务、电信、金融等垂直行业的应用占比也在快速攀升,有力地支撑了业务系统重构。工信部信息技术发展司二……同样是36000分,詹姆斯用了19年时间,那贾巴尔和马龙呢?同样是36000分,詹姆斯用了19年时间,那贾巴尔和马龙呢?在詹姆斯37岁生日的前一天,湖人在客场挑战火箭队的比赛中,詹皇拿下了32分11篮板11助攻的三双数据,当然这场……用眼过度酸涩疲劳?招护眼明目又醒脑盯著电脑一整天,总会觉得眼睛酸涩、疲劳吗?我们的大脑有掌控视力的部位,要是用眼过度,就会让大脑超出负荷。毕竟大脑的其中一个部位长时间维持运转,会使大脑喘不过气。这情形跟在外面累……不生个女儿收不了场!准爸爸在医院陪产,却盯着邻床女婴迈不动步曾经有一个关于爸爸对待孩子态度的测验,他们将录音笔放在宝爸身上,发现他们对女儿说的话比儿子多5倍。不知从何时开始,年轻夫妻和家里老人都开始更喜欢女孩儿了,当着外人的面也丝……StrategyPattern教你秒变神枪手作者:若采作者案:本文介绍的是StrategyPattern(策略模式)。干货满满,希望阅读后你能有所收获目的做一件事情有不同的实现方式,可以将变化的部分和不变的部……苹果上线闪送服务iPhone三小时送到家8月1日,苹果对AppleStore线上商店进行了更新维护,有用户发现,在更新后,网站多出了一个耐人寻味的新标识。维护后,商品页的顶栏除了此前的送货地点、预计发货时间、线下取货……
美媒台积电已做好最坏的打算东风纳米BOX起售6。57万,续航331km,支持快充!大赢家!男篮天才国手怀抱双胞胎乐开花,与妻子16岁定情相爱8浪姐3三公分组及歌单曝光3位姐姐遭淘汰,王心凌上演武侠风中兴通讯上半年营收同比增长12。7,三大业务均实现双位数增长两大佬齐呼向我开炮!壮士断腕,上汽长安都准备好了?科尔穆迪非常冷静不像19岁新秀打的几分钟里贡献巨大CBA4消息!威廉姆斯去山西?易建联加练,辽宁后备球员不足喜忧参半!中国金花夺冠,张帅错失世界第1,18岁天才登顶创神林志颖的老婆越来越美了,穿短裤出门很有活力,看着不像孩子妈2022年换手机参考这3款,耗电少性能强还不贵,用5年不卡顿双十一买手机要舍得下本!华为一加OPPO推荐这几款,久用不卡《乡下人家》教学反思什么查就知道手机码被定位吗(手机查找对方手机位置)假如妈妈生二胎作文孕妇长副乳影响胎儿和哺乳吗高转送股票(股票高送转一览表)北京恒昌创始人兼CEO秦洪涛荣膺十年杰出商业领袖奖田忌赛马告诉我们什么田忌赛马告诉我们什么道理樱花脱排油烟机好不好令人难忘的一件事色彩心理招贴设计论文组合最新机场街拍姑娘们时尚又保暖老年人保健老年人喝这些汤身体更加健康

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找