优化前提
- 【设计模式】之策略模式
- 【设计模式】之工厂模式(三种)
- 【设计模式】之模板方法模式
前言
我们之前也学习了不少设计模式,今天给大家介绍一个案例,帮助大家更加熟悉设计模式,并能够在自己写项目的时候能够下意识的使用设计模式,避免写出屎山代码。🌈
提示:不清楚策略、工厂、模板方法模式的小伙伴可以参考上方文章。
一、 抛出屎山代码
我就以一个简单的代码模拟下业务,像我们平时写项目的时候,这种if-else语句非常常见,比如说:在判断支付类型的时候,在参数校验的时候等等。过多的if-else,会使代码冗余、可读性不好,最重要的是违反了“开闭原则”,拓展性非常的差,后面的同事看了后会非常的痛苦,内心一顿臭骂,为了避免被后面的同事吐槽谩骂,我们要写出更加优雅的代码。
void Example1(){String name = "小杰";if (name.equals("刘二")){System.out.println("刘二完成任务");} else if (name.equals("张三")) {System.out.println("张三完成任务");} else if (name.equals("李四")) {System.out.println("李四完成任务");} else if (name.equals("王五")) {System.out.println("王五完成任务");} else if (name.equals("赵六")) {System.out.println("赵六完成任务");} else if (name.equals("苏七")) {System.out.println("苏七完成任务");}}
二、如何解决
我们一步步引入设计模式,帮助大家理解
1.使用策略模式
分析代码
我们可以将if里面执行的代码可以看作一个个不同的策略,这样我们就可以引入策略模式去优化下面代码。
优化代码
首先,我们定义一个策略接口。
public interface Handler extends InitializingBean {void show();
}
public class LiSi implements Handler{//执行相应的策略@Overridepublic void show() {System.out.println("李四完成了任务");}//这个方法是策略类初始化后需要执行的逻辑,这个我们先不管@Overridepublic void afterPropertiesSet() throws Exception {Factory.register("李四",this);}
}......
优化后代码
void OnlyStrategy(){String name = "小杰";if (name.equals("刘二")){new LiuEr().show();} else if (name.equals("张三")) {new ZhangSan().show();} else if (name.equals("李四")) {new LiSi().show();} else if (name.equals("王五")) {new WangWu().show();} else if (name.equals("赵六")) {new ZhaoLiu().show();} else if (name.equals("苏七")) {new SuQi().show();}}
2.引入工厂模式
分析代码
虽然我们引入了策略模式,但是仍然未解决if-else语句,并且每次使用策略都必须先new出来,后续拓展仍然需要添加if-else代码,这样看起来代码更加复杂了,性能更差了。别急,我们继续添加工厂模式,继续优化代码。
优化代码
我们定义一个工厂,让工厂帮我们去生产对应的对象。
public class Factory {//我们将策略类存入HashMap里面private static Map<String, Handler> map = new HashMap<>();//根据name获取对应的策略类public static Handler getInvokeStrategy(String name){return map.get(name);}//将策略类放入map里面public static void register(String name,Handler handler){if (StringUtils.isEmpty(name) || null == handler){return;}map.put(name,handler);}
}
这里给大家解释afterPropertiesSet()方法里面的逻辑
public class LiSi implements Handler{@Overridepublic void show() {System.out.println("李四完成了任务");}@Overridepublic void afterPropertiesSet() throws Exception {//策略类初始化后,自动将策略类注册到HashMap里面Factory.register("李四",this);}
}
优化后代码
//我们成功的干掉了if-else
void haveFactory(){String name = "张三";Handler handler = Factory.getInvokeStrategy(name);handler.show();}
3.引入模板方法模式
分析代码
到这里虽然我们成功的干掉了if-else语句,但是又引出了一个问题,
String name = "小杰";if (name.equals("刘二")){System.out.println("刘二完成任务");} else if (name.equals("张三")) {System.out.println("张三完成任务");} else if (name.equals("李四")) {System.out.println("李四完成任务");} else if (name.equals("王五")) {return "王五完成了任务";} else if (name.equals("赵六")) {return "赵六完成任务";} else if (name.equals("苏七")) {return "苏七完成任务";}
我们可以看到,五五、赵六、苏七策略跟其他语句的策略并不一样。
解决思路:
- 在策略接口添加不同的策略(不使用)
- 使用模板方法模式,每个策略类实现自己对应的策略(推荐使用)
给大家解释下为什么不使用第一种,如果我们在策略接口添加不同的策略,我们的策略类就必须要实现所以的策略,但是策略类并不需要实现所有的策略,它只需要实现自己的那一个策略,所以这个思路不可行。
优化代码
我们将策略接口改为策略抽象类
public abstract class AbstractHandler implements InitializingBean {//策略1public void show(String name){ throw new UnsupportedOperationException();}//策略2public String eat(String name){ throw new UnsupportedOperationException();}
}
当然,我们的工厂和策略类也要修改,张三策略类和王五策略类实现不同的策略。
//策略工厂
public class Factory2 {//将Handler改为AbstractHandlerprivate static Map<String, AbstractHandler> map = new HashMap<>();public static AbstractHandler getInvokeStrategy(String name){return map.get(name);}public static void register(String name,AbstractHandler handler){if (StringUtils.isEmpty(name) || null == handler){return;}map.put(name,handler);}
}
//张三策略类
@Component
public class WangWu extends AbstractHandler {@Overridepublic String eat(String name) {return "王五吃东西";}@Overridepublic void afterPropertiesSet() throws Exception {Factory2.register("王五",this);}
}
//王五策略
@Component
public class ZhangSan extends AbstractHandler {@Overridepublic void show(String name) {System.out.println("张三完成了任务");}@Overridepublic void afterPropertiesSet() throws Exception {Factory2.register("张三",this);}
}
......
优化后代码
@Testvoid haveTemplate(){String name1 = "王五";AbstractHandler handler1 = Factory2.getInvokeStrategy(name1);System.out.println(handler1.eat(name1));String name2 = "张三";AbstractHandler handler2 = Factory2.getInvokeStrategy(name2);handler2.show(name2);}
随着通过我们一步步的添加设计模式,使我们的代码更加简洁,也符合了“开闭原则”,到这里,我们就优化完成了。
总结
虽然设计模式帮助我们优化了代码,是代码更加的规范,但是,切不可为了使用设计模式而去使用设计模式,在某种业务场景使用if-else语句可能比设计模式更加适合,所以大家要结合业务场景,选出最优的解决方法。
今天的分享就到这里,喜欢的小伙伴可以一键三连哦,我们下期再见。✋✋✋