优化前提
前言
我们之前也学习了不少设计模式,今天给大家介绍一个案例,帮助大家更加熟悉设计模式,并能够在自己写项目的时候能够下意识的使用设计模式,避免写出屎山代码。🌈
提示:不清楚策略、工厂、模板方法模式的小伙伴可以参考上方文章。
一、 抛出屎山代码
我就以一个简单的代码模拟下业务,像我们平时写项目的时候,这种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{
//执行相应的策略
@Override
public void show() {
System.out.println("李四完成了任务");
}
//这个方法是策略类初始化后需要执行的逻辑,这个我们先不管
@Override
public 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{
@Override
public void show() {
System.out.println("李四完成了任务");
}
@Override
public 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 {
//策略1
public void show(String name){ throw new UnsupportedOperationException();}
//策略2
public String eat(String name){ throw new UnsupportedOperationException();}
}
当然,我们的工厂和策略类也要修改,张三策略类和王五策略类实现不同的策略。
//策略工厂
public class Factory2 {
//将Handler改为AbstractHandler
private 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 {
@Override
public String eat(String name) {
return "王五吃东西";
}
@Override
public void afterPropertiesSet() throws Exception {
Factory2.register("王五",this);
}
}
//王五策略
@Component
public class ZhangSan extends AbstractHandler {
@Override
public void show(String name) {
System.out.println("张三完成了任务");
}
@Override
public void afterPropertiesSet() throws Exception {
Factory2.register("张三",this);
}
}
......
优化后代码
@Test
void 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语句可能比设计模式更加适合,所以大家要结合业务场景,选出最优的解决方法。
今天的分享就到这里,喜欢的小伙伴可以一键三连哦,我们下期再见。✋✋✋