重构大量if-else叠加: 工厂模式+策略设计模式+模板模式
现有三个简单的if-else
判断逻辑业务代码,如下图所示
这种嵌套几个其实还好,但是通常开发十几个if-else
确实是家常便饭
if-else
的数量一多,代码非常臃肿,耦合性非常高
如果需要增加或者删除一个if-else,就需要对代码进行很繁琐的修改,但是其实耐心点改起来还好,不过可能会掉头发哦
并且这种if-else
的编写破坏了设计模式六大原则中的里氏开闭原则(对拓展开放,修改关闭),不利于后续的变动和修改
为了使代码符合优雅的设计模式和编码形式,现在提供一种新的修改思路供大家参考
以下是改造前的代码:
// 三个if - else 的编码修改
@SpringBootTest
class ConcurrencyApplicationTests {
@Test
void contextLoads() throws InterruptedException {
String name = "周杰伦";
if (name.equals("周杰伦")){
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("周杰伦出新专辑了吗");
}
else if (name.equals("JJ")){
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("小十四啥时候出哦");
}
else if (name.equals("Eason")){
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("陈老板减肥啊");
}
}
}
改造后:
@SpringBootTest
class ConcurrencyApplicationTests {
@Test
void contextLoads() {
String name = "周杰伦";
Handler invokeStrategy = Factory.getInvokeStrategy(name);
invokeStrategy.method(name);
}
}
使用设计模式的改造方法
我们先把if
内部的业务逻辑提取出来
利用策略设计模式来编写一个接口
/**
* 策略设计模式
*/
public interface Handler extends InitializingBean {
public void method(String name);
}
将你的业务逻辑从if
中提取出来,写在实现类中
package com.zhou.concurrency.handler;
import java.util.concurrent.TimeUnit;
public class Method1Handler implements Handler {
@Override
public void method(String name) {
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("周杰伦啥时候发新专辑哦");
}
// 这里先不用管,后面会说到
@Override
public void afterPropertiesSet() throws Exception {
}
}
剩下的几个类就省略了,其实就是复制粘贴的重复工作
将其修改成如下形式,但是这个也只是将其单独提出来,和写一个单独的函数没啥区别
@Test
void contextLoads() {
String name = "周杰伦";
if (name.equals("周杰伦")){
new Method1Handler().method(name);
}
else if (name.equals("JJ")){
new Method2Handler().method(name);
}
else if (name.equals("Eason")){
new Method3Handler().method(name);
}
}
为了进一步解决if
判断,我们使用工厂模式解决
工厂模式可以注册产品,获得产品,以及存储产品
public class Factory {
// map存储参数以及其对应的Handler方法
private static Map<String, Handler> strategyMap = new HashMap<>();
// 从map中取出Handler方法,取出工厂内的产品
public static Handler getInvokeStrategy(String str) {
return strategyMap.get(str);
}
// 将键值对注册,添加工厂产品
public static void register(String str, Handler handler) {
// 如果输入进来的键值是空,不符合要求就直接返回
if (StringUtils.isEmpty(str) || handler == null) {
throw new IllegalArgumentException("你输入的键值对有空值,不符合要求");
}
strategyMap.put(str,handler);
}
}
之后,修改一下之前的Handler实现类,并加入@Component
注解,其他的几个业务逻辑同理
@Component
public class Method1Handler implements Handler {
// 业务逻辑
@Override
public void method(String name) {
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("周杰伦啥时候发新专辑哦");
}
// 类初始化自动注册
@Override
public void afterPropertiesSet() throws Exception {
// 这个类初始化的时候,就会自动注册
Factory.register("周杰伦",this);
}
}
回到主函数, 改写一下即可:
@SpringBootTest
class ConcurrencyApplicationTests {
@Test
void contextLoads() {
String name = "周杰伦";
Handler invokeStrategy = Factory.getInvokeStrategy(name);
invokeStrategy.method(name);
}
}
后续如果还需要增加业务逻辑,就新增加一个Handler的实现类就好了
加模板设计方法
如果业务逻辑是两种业务逻辑,比如有的是输出一句话,有的是return一句话
那么Handler单一的method接口可能就不适用了,因为你在接口多写一个方法,其他不需要的地方你实现一个空方法,肯定要被老大骂的
@SpringBootTest
class ConcurrencyApplicationTests {
@Test
String design(){
String name = "周杰伦";
if (name.equals("周杰伦")){
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("周杰伦出新专辑了吗");
}
else if (name.equals("JJ")){
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("小十四啥时候出哦");
}
else if (name.equals("Eason")){
for (int i = 0; i < 5; i++) {
System.out.println(name + "我爱你");
}
System.out.println("陈老板减肥啊");
}
// 新增加的逻辑代码 返回值
else if (name.equals("jojo")){
return "欧拉欧拉欧拉欧拉";
}
else if (name.equals("老大")){
return "进展如何";
}
return null;
}
}
改进一下我们的Handler类,引入模板方法模式
// 模板方法模式
public abstract class AbstractHandler implements InitializingBean {
public void method(String name){
throw new UnsupportedOperationException();
}
public String method2(String name){
throw new UnsupportedOperationException();
}
}
需要用到method就改写method,需要用到method2就改写method2
@Component
public class Method4Handler extends AbstractHandler {
// 业务逻辑
public String method2(String name) {
return "进展如何";
}
// 这里不用管
@Override
public void afterPropertiesSet() throws Exception {
// 这个类初始化的时候,就会自动注册
Factory.register("老大",this);
}
}
最终代码:
@Test
void contextLoads() {
String name = "老大";
AbstractHandler invokeStrategy = Factory.getInvokeStrategy(name);
// invokeStrategy.method(name);
String s = invokeStrategy.method2(name);
System.out.println(s);
}