范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

StrategyPattern教你秒变神枪手

  作者:若采
  作者案:本文介绍的是 Strategy Pattern (策略模式)。干货满满,希望阅读后你能有所收获 目的
  做一件事情有不同的实现方式,可以将变化的部分和不变的部分剥离开,去除大量的 if/else,提供高扩展性。  例子代码
  比如我们想要带妹吃鸡,就要成为一个神枪手。在各种枪战游戏中,有各种不同的枪,我们要根据射程的不同选择不同的枪进行射击。
  如果枪的子弹数量都不富裕,我们要用最少的子弹,最合适的方法达到最强伤害,最终大吉大利。
  当我们距离对手:  1米以内,使用平底锅(想我当时三级头三级甲,手持 AKM,满血满状态,三级包里药包无数,到了决赛圈被平底锅堵在墙角打死啦 );  100 米左右,使用冲锋枪;  超过 1000 米,使用狙击枪(对于我这样的小菜鸡,基本流程是开一枪没打中,暴露位置,被别人一狙打死...囧)。  /**  * 面条式代码判断最强武器  */ public class NoodlesKillProcessor {         /**      * 根据距离判断最好的武器击杀对手      * @param distance      */     @BadSmell     public static void killByDistance(int distance) {                 if(distance < 0) {                         throw new RuntimeException("距离咋还能是负数呢?");         }                 if(distance >= 0 && distance < 1) {             System.out.println("发现敌人");             System.out.println("两步快速走过去");             System.out.println("掏出平底锅呼他");                      return;         }                 if(distance >= 1 && distance < 10) {             System.out.println("发现敌人");             System.out.println("快速走过去");             System.out.println("掏出手枪打他");                        return;         }                 if(distance >= 10 && distance < 100) {             System.out.println("发现敌人");             System.out.println("身体站直, 心态稳住");             System.out.println("掏出冲锋枪打他");                      return;         }                 if(distance >= 100 && distance < 1000) {             System.out.println("发现敌人");             System.out.println("身体蹲下降低后坐力");             System.out.println("掏出步枪");             System.out.println("打开 3 倍镜");             System.out.println("开枪射击");                         return;         }                 if(distance >= 1000) {             System.out.println("发现敌人");             System.out.println("趴在草丛里苟着");             System.out.println("掏出狙击枪");             System.out.println("打开 8 倍镜");             System.out.println("开枪射击");                         return;         }     } }问题分析
  我觉得这有 3 个问题,具体分析如下:
  01 可读性问题
  我看这么多 if/else 语句,里面的 sout 语句目前三四行也还好,如果我们有上百行的语句,里面也有很多 if/else,这样都不知道下个主 if 跑哪去啦
  02 重复性问题
  全都需要发现敌人,如果发现敌人是个成百上千行代码,就很麻烦啦。
  03 可维护性问题
  如果这时候我们新增了一种枪,比如是霰弹枪,适用 10 到 20 的时候使用,这时候我们就需要在加一个 if 语句如下:  /**  * 面条式代码判断最强武器  */  public class NoodlesKillProcessor {         /**      * 根据距离判断最好的武器击杀对手      * @param distance      */     @BadSmell     public static void killByDistance(int distance) {                 if(distance < 0) {                         throw new RuntimeException("距离咋还能是负数呢?");         }                 if(distance >= 0 && distance < 1) {             System.out.println("发现敌人");             System.out.println("两步快速走过去");             System.out.println("掏出平底锅呼他");                      return;         }                 if(distance >= 1 && distance < 10) {             System.out.println("发现敌人");             System.out.println("快速走过去");             System.out.println("掏出手枪打他");                        return;         }                 if(distance >= 10 && distance < 20) {             System.out.println("发现敌人");             System.out.println("身体站直, 瞄准");             System.out.println("打一枪算一枪");                        return;         }                 if(distance >= 20 && distance < 100) {             System.out.println("发现敌人");             System.out.println("身体站直, 心态稳住");             System.out.println("掏出冲锋枪打他");                      return;         }                 if(distance >= 100 && distance < 1000) {             System.out.println("发现敌人");             System.out.println("身体蹲下降低后坐力");             System.out.println("掏出步枪");             System.out.println("打开 3 倍镜");             System.out.println("开枪射击");                         return;         }                 if(distance >= 1000) {             System.out.println("发现敌人");             System.out.println("趴在草丛里苟着");             System.out.println("掏出狙击枪");             System.out.println("打开 8 倍镜");             System.out.println("开枪射击");                         return;         }     } }
  这个看着也没啥大问题的样子,不就是加了个 if 么,但是由于我们改动了这个文件,测试同学问我们需要测试哪些功能,说是测一种枪需要 5 天
  问题来啦,本来说是你增加一种枪, 需要测 5 天,但是现在你说改了这文件,上下可能有些局部变量共享的,或者有些方法可能改了入参的值,这些有负作用的方法被调用啦,所以可能狙击枪也得测一测,可能手枪也得测一测。
  测试同学崩了,本来 5 天的工作量,搞成了 5 * 6 天,一个月都在测枪
  初步尝试解决
  我们先定义好一个基础类,解决一下可读性问题和重复性问题。
  定义一个基础武器类:  /**  * 抽象的枪  */ public abstract class Weapon {         /**      * 发现敌人      */     protected void findEnemy() {         System.out.println("发现敌人");     }         /**      * 开枪前的动作      */     protected abstract void preAction();         /**      * 开枪      */     protected abstract void shoot();         /**      * 整体的动作      */     public void kill() {         findEnemy();         preAction();         shoot();     } }
  逐个实现武器的具体类、平底锅、冲锋枪、步枪等类如下:  /**  * 平底锅  */ public class Pan extends Weapon {         @Override     protected void preAction() {         System.out.println("两步快速走过去");     }         @Override     protected void shoot() {         System.out.println("掏出平底锅呼他");     } } /**  * 手枪类  */ public class Pistol extends Weapon {         @Override     protected void preAction() {         System.out.println("快速走过去");     }         @Override     protected void shoot() {         System.out.println("掏出手枪打他");     } } /**  * 霰弹枪  */ public class Shotgun extends Weapon {         @Override     protected void preAction() {         System.out.println("身体站直, 瞄准");     }         @Override     protected void shoot() {         System.out.println("打一枪算一枪");     } } /**  * 狙击枪  */ public class SniperRifle extends Weapon {     @Override     protected void preAction() {         System.out.println("趴在草丛里苟着");         System.out.println("掏出狙击枪");         System.out.println("打开 8 倍镜");     }     @Override          protected void shoot() {         System.out.println("开枪射击");     } } /**  * 冲锋枪  */ public class SubmachineGun extends Weapon {         @Override     protected void preAction() {         System.out.println("身体站直, 心态稳住");     }         @Override     protected void shoot() {         System.out.println("掏出冲锋枪打他");     } }
  我们的方法就可以改动得更清晰啦  /**  * 抽象出类代码判断最强武器  */ public class WeaponKillProcessor {         /**      * 根据距离判断最好的武器击杀对手      * @param distance      */     @BadSmell     public static void killByDistance(int distance) {                  if (distance < 0) {                          throw new RuntimeException              ("距离咋还能是负数呢?");         }         Weapon weapon = null;                  if (distance >= 0 && distance < 1) {             weapon = new Pan();         } else if (distance >= 1 && distance < 10) {             weapon = new Pistol();         } else if (distance > 10 && distance < 20) {             weapon = new Shotgun();         } else if (distance >= 20 && distance < 100) {             weapon = new SubmachineGun();         } else if (distance >= 100 && distance < 1000) {             weapon = new Rifle();         } else if (distance >= 1000) {             weapon = new SniperRifle();         }              weapon.kill();     } }
  类图如下:
  使用策略模式
  上面的代码没有解决最根本的问题,也就是去除 if/else,所用的方法其实就是将 if else 转换为 for,这样的代码后续添加枪就不需要再增加新的类型啦。
  我们先定义一个通用的策略模式接口如下:  /**  * 策略模式  */ public interface Strategy   {         /*       * 执行策略      * @param request      * @return      */     R executeStrategy(T request); }
  入参和出参都是基本的抽象类:  /**  * 策略模式抽象入参  */ public abstract class AbstractStrategyRequest { } /**  * 策略模式抽象出参  */ public abstract class AbstractStrategyResponse { }
  实现一个武器抽象类实现接口:  public abstract class WeaponStrategy implements  Strategy {         /**      * 发现敌人      */     protected void findEnemy() {         System.out.println("发现敌人");     }         /**      * 开枪前的动作      */     protected abstract void preAction();         /**      * 开枪      */     protected abstract void shoot();         /**      * 获取距离范围      * @return      */     protected abstract Range queryDistanceRange();         /**      * 整体的动作      */     public void kill() {         findEnemy();         preAction();         shoot();     }         @Override     public AbstractStrategyResponse         executeStrategy(WeaponStrategyRequest request) {         System.out.println("距离敌人 " + request.getDistance());         kill();                 return null;     } }
  其中的 Range 类实现如下:  /**  * 范围类  * @param   */ @Data @AllArgsConstructor public class Range> {         private T start;         private T end;         public Range(T start, T end) {                 this.start = start;                 this.end = end;     }         private boolean isIncludeStart = true;         private boolean isIncludeEnd = false;         /**      * 判断是否在范围内      * @param target      * @return      */     public boolean inRange(T target) {                 if(isIncludeStart) {                         if(start.compareTo(target) > 0) {                                 return false;             }         } else {                         if(start.compareTo(target) >= 0) {                                 return false;             }         }                 if(isIncludeEnd) {                         if(end.compareTo(target) < 0) {                                 return false;             }         } else {                         if(end.compareTo(target) <= 0) {                                 return false;             }         }                 return true;     } }
  依次实现这个抽象武器策略类:  /**  * 平底锅  */ public class PanStrategy extends WeaponStrategy {         @Override     protected void preAction() {         System.out.println("二步快速走过去");     }          @Override     protected void shoot() {         System.out.println("掏出平底锅呼他");     }            @Override         protected Range queryDistanceRange() {              return new Range<>(0, 1);     } } /**  * 手枪类  */ public class PistolStrategy extends WeaponStrategy {         @Override     protected void preAction() {         System.out.println("快速走过去");     }         @Override     protected void shoot() {         System.out.println("掏出手枪打他");     }         @Override     protected Range queryDistanceRange() {              return new Range<>(1, 10);     } } /**  * 步枪  */ public class RifleStrategy extends WeaponStrategy {         @Override     protected void preAction() {         System.out.println("身体蹲下降低后坐力");         System.out.println("掏出步枪");         System.out.println("打开 3 倍镜");     }         @Override     protected void shoot() {         System.out.println("开枪射击");     }         @Override     protected Range queryDistanceRange() {              return new Range<>(100, 1000);     } } /**  * 霰弹枪  */ public class ShotgunStrategy extends WeaponStrategy {         @Override     protected void preAction() {         System.out.println("身体站直, 瞄准");     }         @Override     protected void shoot() {         System.out.println("打一枪算一枪");     }         @Override     protected Range queryDistanceRange() {              return new Range<>(10, 20);     } } /**  * 狙击枪  */ public class SniperRifleStrategy extends WeaponStrategy {         @Override     protected void preAction() {         System.out.println("趴在草丛里苟着");         System.out.println("掏出狙击枪");         System.out.println("打开 8 倍镜");     }         @Override     protected void shoot() {         System.out.println("开枪射击");     }         @Override     protected Range queryDistanceRange() {              return new Range<>(1000, Integer.MAX_VALUE);     } } /**  * 冲锋枪  */ public class SubmachineGunStrategy extends WeaponStrategy {         @Override     protected void preAction() {         System.out.println("身体站直, 心态稳住");     }         @Override     protected void shoot() {         System.out.println("掏出冲锋枪打他");     }         @Override     protected Range queryDistanceRange() {              return new Range<>(20, 100);     } }
  定义一个上下文类来对入参进行路由:  /**  * 策略上下文, 用来路由策略  */ public class StrategyContext {     public static final List         WEAPON_STRATEGYS = new ArrayList<>();     static {         WEAPON_STRATEGYS.add(new PanStrategy());         WEAPON_STRATEGYS.add(new PistolStrategy());         WEAPON_STRATEGYS.add(new RifleStrategy());         WEAPON_STRATEGYS.add(new ShotgunStrategy());         WEAPON_STRATEGYS.add(new SniperRifleStrategy());         WEAPON_STRATEGYS.add(new SubmachineGunStrategy());     }     public static void execute(Integer distance) {         WEAPON_STRATEGYS.stream().         filter((weaponStrategy -> {             Range integerRange =                 weaponStrategy.queryDistanceRange();             return integerRange.inRange(distance);         })).         findAny().         get().         executeStrategy(             new WeaponStrategyRequest(distance));     } }
  最后在主方法里面调用就好啦:  public class App {     public static void main(String[] args) {                 StrategyContext.execute(89);     } }
  结果如下:  距离敌人 89
  发现敌人
  身体站直,心态稳住
  掏出冲锋枪打他
  类图如下:
  加入我们
  我们来自字节跳动飞书商业应用研发部(Lark Business Applications),目前我们在北京、深圳、上海、武汉、杭州、成都、广州、三亚都设立了办公区域。我们关注的产品领域主要在企业经验管理软件上,包括飞书 OKR、飞书绩效、飞书招聘、飞书人事等 HCM 领域系统,也包括飞书审批、OA、法务、财务、采购、差旅与报销等系统。
  点击「链接」,欢迎各位加入我们!

风从草原来休闲巴蜀韵2023川蒙百万人互游文化旅游推广活动来源人民网内蒙古频道为深化内蒙古自治区与山东湖北四川等主力客源地省份的文化和旅游的交流与合作,活跃夏秋季旅游市场,激发游客来内蒙古旅游的积极性,内蒙古自治区文化和旅游厅赴山东省济南超过50年,珊瑚海风加权路径分布的热带气旋危害的发散文丨波波百谈编辑丨波波百谈起源于珊瑚海的热带气旋(TC)对其周围的沿海地区构成了重大危害。此外,该地区还没有很好地了解TC轨道的不稳定性质。因此,研究人员根据最大风权质心的K均值聚聚焦GetChat赋能社交网络带你玩出新花样在Web3时代,社交网络仍然扮演着思想市场和公共论坛的角色,Web3革命是文化金融和社会的,这场革命的影响将渗透到网络空间的每一个角落。从这个角度看,革命的前提条件都具备了独立的金第7章数组数组的引入1练习引入packagemainimportfmtfuncmain()score195score291score339score460score521sumscore1s张小飞的Java之路字符串(重点)写在前面视频是什么东西,有看文档精彩吗?视频是什么东西,有看文档速度快吗?视频是什么东西,有看文档效率高吗?诸小亮接下来我们就需要学习String张小飞这不就是字符串么,前面也用过放大镜下的月球,没有水的水星(Mercury)水星是太阳系的八大行星中最小且最靠近太阳的行星。轨道周期是87。9691天,116天左右与地球会合一次,公转速度远远超过太阳系的其它行星。水星是表面昼夜温差最大的行星,大气层极为稀女性机器人能替代女性吗?女性机器人虽然在功能上可以模仿人类女性的某些特征,但是总体而言,它们并不能真正替代人类女性。首先,无论机器人再真实,它们始终是人工智能,缺少了人类的情感和思维。其次,机器人无法像人ChatGPT正在被应用科技之颠大家好,我是对什么信息都感兴趣的幕落。前段时间ChatGPT的热潮引起了许多人的思考。人工智能是否能替代我的职业?人工智能真的很厉害吗?人工智能创造的东西是什么样的?近来我伽师蓝莓快递销往全国各地石榴云新疆日报讯(记者范琼燕报道)伽师县蓝莓大批量上市了,通过电商抖音直播带货,平均每天有近200单由顺丰快递发往全国各地。4月16日下午,新疆顺丰速运有限公司喀什片区伽师业务部快一篇斯坦福大学的论文引出对AI意识的思考这是一篇斯坦福大学计算心理学教授迈克尔柯辛斯基(MichaelKozinski)不久前发表的一篇论文,标题是TheoryofMindMayHaveSpontaneouslyEmer足协新领导遭实名举报,名记质疑包庇假球,调查材料上交后没下文国足前主帅李铁被带走调查之后,已经有多名大老虎也落马了,比如杜兆才陈戌源于洪臣陈永亮刘奕黄松王小平,每一个单独拎出来都是响当当的大人物。这也表明了中国足球反腐扫赌的决心,只要涉及到
中国量子计算机太强了比世界第一超算还快一亿亿亿倍量子计算机,一直是我国引领世界的领域,九章量子计算机则是这个领域的标杆。不过最近我国的工程技术人员再一次刷新了这个标杆。去年12月,中国研制成功的量子计算机九章,求解高斯玻色取样数iPhone13到手一整月后,这些首发用户后悔了吗?谈谈我的使用体验iPhone13发布一个多月了,我买的是星光色128G版本,和几个朋友一起官网预约,9月25号在applestore取的货。至今使用了一个多月,给大家分享下使用体验1续航按官网的说真让李迅雷说中了?手持2套房的家庭,未来将面临什么?对全国数以亿计的购房者来说,楼市传来一个好消息近6年来,新房实现首跌。根据国家统计局的数据显示,我国70城新房价格下跌拐点已经出现,销售价格环比呈现下降态势,其中三四线城市房价变化这个双十一,李佳琦也没有最低价,品牌逃离大主播?文AI财经社张梦依编辑杨洁双十一并没有被李佳琦杀死。相反的是,品牌商们已经动起了和李佳琦薇娅这些头部主播解绑的心思。今年的双十一来得比以往更早一些。在10月20日预售夜当晚,李佳琦A股行情逐渐明朗,股市开始转向了有位散户提过1个问题,为什么每次他买了股票就下跌,卖了股票就上涨,主力真在乎他那一点筹码?这是大众问题,在股市遇到的人多了,一买就跌一卖就涨,问题不是主力盯着你的小筹码,这种情况绕善良是一种愿景善最宝贵,生命用不尽心好田,消耗生命。那些做善事的人,看似笨拙地花费时间和精力,却有着深刻的洞察力。选择那些行善的人,好运会暗中奖赏你。01善良是一种选择明朝的时候,有个姓张的官员你迟早会明白,有的人,没必要联系了,纯属自讨没趣这一生有的人走进你的生命,只是为了给你匆匆上一课,而你却过分重感情,舍不得这个,又怀念着那个,让自己在人际关系里沉沦,浪费了大好青春。有人对你真心,值得你珍惜,而有的人对你只有利用给军衔不要,毛主席发话才听,三位忠心耿耿保护毛主席的卫士知识辞海计划在毛主席的一生中,有很多保护他的人,包括我军个子最高的罗瑞卿大将,还有仅次于罗瑞卿的张宗逊上将,这两位给毛主席当过卫士长的最后都成了开国将军,而还有一位保护毛主席的最后近场聆听之美KEFLS50Meta书架箱山灵EA5流媒体功放说起使用同轴单元的书架箱,大家也许首先就会想到极具市场知名度的英国KEF及其产品。KEF又是谁?音响界公认的英国殿堂级音响品牌,一直专注于音响领域,相当于篮球界的迈克尔乔丹,音乐界父亲是歪瓜裂枣,女儿却貌美如花?这7位星二代的长相好奇妙俗话说桂实生桂,桐实生桐,父母的容貌是否优秀,很大程度上决定了儿女的长相。在娱乐圈中就有很多这样的例子,不少星二代都继承了父母的优秀基因,从小就长得非常出众。当然,这这种事也并不是有种遗传叫佟大为儿子,实力演绎逆袭生长,网友女儿怎么办本文原原创丨乖妈娱乐圈的星二代们,向来是大家关注热议的对象,热搜上也经常爆出相关消息田亮的女儿森碟腿好长啊!张柏芝儿子长大了,越长越像爸爸了!李湘王岳伦的女儿王诗龄变瘦了,女大十八