1.灵魂三问
所以,对于上述三个问题,我写了此随笔,然而————然并卵
这篇文章并不能让你不接手前人项目,并不能让你看懂没有注释的业务代码,也并不能让你以后不碰到if/else轰击波,但是——系尬系
鲁迅先生曾倡导过,如果你觉得政府腐败,那么你就应该努力考取公务员从政,去内部解决腐败;如果你觉得你的家乡建设不够美丽,那么你应该去建设他;如果你觉得人民素质不够高,那么你应该提高自身素质,以身作则;如果你觉得这功能完全是业务无理取闹,产品瞎接,那么你应该——好吧,业务爸爸一切都好。
瞎扯了半天,下面进入正题:
很多情况下,都没有一次到位得产品,也通常没有一次到位的业务需求,所以在后期的功能扩展中,很可能会造成不停的对原代码加入if/else分支判断,来满足新的业务需求,然而这对于后接手的程序员来说,在一堆if/else,几百行代码中去快速理解逻辑,并加入扩展,无疑是件很蛋疼的事(好吧,其实我的真实原因是:看起来有点丑),所以,如何改造自己的if/else代码,让其看的不显臃肿,直观简洁,我百度了一下,简单写了份在springboot
环境下,利用策略模式改造代码的随笔,作为新知识的get体会!(好吧,策略模式其实很常见)
2.什么是策略模式
策略模式(Strategy Pattern):一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
运行时随时更改,有没有想到spring的自动注入?灵活,易扩展这也是其特点之一。有没有具体的实现步骤呢?有的!
3.简单实现步骤
简单的一个需求
首先,先假想一个简单的业务——新需求上,这个功能暂时有三个分支判断,三个分支对应不同的执行逻辑:
- 1——孙悟空逻辑
- 2——二师兄逻辑
- 3——唐僧逻辑
那么,首先,我们当然可以用if/else,switch,来做分支判断解决,好的解决,项目上线,后期扩展——
业务A有发话了,我觉得应该有4——沙师弟逻辑,对吧,是这样吧!好,我再加一个if,没问题的!
业务B突然有话发话了,我觉得应该有5——三只眼逻辑,对吧,不能没有二郎神啊!好,我再加一个if,ojbk
!
业务C突然有想法了,咋不能忘了6——小白马吧,对吧,这么辛苦!嗯~~~,可以,应该可以快速实现!
业务D又来了,我觉得那白骨精挺漂亮的,是吧?你(漂亮你大爷)!!!!!!!好,还有没有漂亮的?
所以,这个分支的类,看起来有点难受!
策略模式实现步骤
好的话不多说,策略模式下,我们可以怎么解决这个问题呢?
- 首先,可以建立一个枚举类,用于存储分支判断的条件(也可以用静态变量)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public enum WestCommand {
W_SuWuKong(1,"孙爷爷","monkeyCommand"), W_ZhuBaJie(2,"二师兄","pigCommand"), W_TangSeng(3,"和尚","monkCommand"); private int value;
private String descreption;
private String beanName;
private WestCommand(int value,String descreption,String beanName){ this.value=value; this.descreption=descreption; this.beanName=beanName; }
public int getValue(){ return value; }
public String getDescreption(){ return descreption; }
public String getBeanName(){ return beanName; } public static WestCommand getInstance(int value) { for(WestCommand type : WestCommand.values()) { if(type.getValue() == value) { return type; } } return null; }
}
|
这个类用于存储分支判断条件,,,,,
- 建立策略角色接口
1 2 3 4 5 6 7 8 9 10 11 12 13
| /** * @说明: * @类型名称:StrategyCommand * @创建者: Raiden * @创建时间: 2020/2/11 12:01 * @修改者: Raiden * @修改时间: 2020/2/11 12:01 */ public interface StrategyCommand {
String process(); }
|
- 创建具体策略角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| /** * @说明:唐僧 * @类型名称:MonkeyCommand * @创建者: Raiden * @创建时间: 2020/2/11 12:02 * @修改者: Raiden * @修改时间: 2020/2/11 12:02 */ @Service public class MonkCommand implements StrategyCommand { @Override public String process() { return "和尚不曾调戏妖精了,施主还是别问了!!"; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| /** * @说明:孙悟空 * @类型名称:MonkeyCommand * @创建者: Raiden * @创建时间: 2020/2/11 12:02 * @修改者: Raiden * @修改时间: 2020/2/11 12:02 */ @Service public class MonkeyCommand implements StrategyCommand { @Override public String process() { return "你孙爷爷叫你回家吃饭了!!"; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| /** * @说明:二师兄 * @类型名称:MonkeyCommand * @创建者: Raiden * @创建时间: 2020/2/11 12:02 * @修改者: Raiden * @修改时间: 2020/2/11 12:02 */ @Service public class PigCommand implements StrategyCommand { @Override public String process() { return "你二师兄走位相当风骚!!"; } }
|
- 创建上下文,获取具体角色
这里首先需要创建一个spring的工具类,用于根据id获取bean
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| /** * @说明: * @类型名称:StrategeContext * @创建者: Raiden * @创建时间: 2020/2/11 14:41 * @修改者: Raiden * @修改时间: 2020/2/11 14:41 */ @Component public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext context;
@Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringUtils.context==null){ SpringUtils.context=applicationContext; System.out.println("初始化容器成功------------"); } } //获取context public static ApplicationContext getContext(){
return SpringUtils.context; }
//通过名称获取bean public static Object getBean(String beanName){
return getContext().getBean(beanName);
}
/** * 通过类型获取bean * @param tClass * @param <T> * @return */ public static <T> T getBean(Class<T> tClass){
return getContext().getBean(tClass); }
public static <T> T getBean(String beanName,Class<T> classType){
return getContext().getBean(beanName,classType);
}
}
|
然后,创建上下文
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| /** * @说明: * @类型名称:StrategyContext * @创建者: Raiden * @创建时间: 2020/2/11 15:05 * @修改者: Raiden * @修改时间: 2020/2/11 15:05 */ public class StrategyContext {
/** * 获取对应的command实现类 * @param value * @param classType * @param <T> * @return */ public static <T> T getStrategyBean(Integer value,Class<T> classType){ return SpringUtils.getBean( WestCommand.getInstance(value).getBeanName(),classType);
}
}
|
在这里,一切准备工作基本算是完成了,下面,我们来看看效果
这里我是利用的springboot+springcloud
创建了一个接口:
相应的控制层:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| /** * @说明: * @类型名称:StrategyCrtl * @创建者: Raiden * @创建时间: 2020/2/11 11:58 * @修改者: Raiden * @修改时间: 2020/2/11 11:58 */ @RestController @RequestMapping("/strategy") public class StrategyCrtl {
@GetMapping("/{number}") public ResponseEntity<String> getMessage(@PathVariable Integer number){
StrategyCommand bean = StrategyContext.getStrategyBean(number, StrategyCommand.class);
return ResponseEntity.ok(bean.process()); } }
|
业务逻辑干掉了if/else,启动服务:
我们看一看看效果:1——孙悟空逻辑

2——二师兄逻辑

3——和尚逻辑

至于后来万一需要漂亮的白骨精,那么怎么做相信不用我多说,这看起来确实比if/else美观了不少,有人说差不多,那是因为业务爸爸层就只跟你说了一句话,万一有几百句呢?
原文链接:https://www.cnblogs.com/raidencool/p/12342237.html
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。