项目中的if else太多了,该怎么重构?


最近跟着公司的大佬开发了一款IM系统,类似QQ和微信哈,就是聊天软件。我们有一部分业务逻辑是这样的

if (msgType = “文本”) {
// dosomething
} else if(msgType = “图片”) {
// doshomething
} else if(msgType = “视频”) {
// doshomething
} else {
// doshomething
}
1
2
3
4
5
6
7
8
9
就是根据消息的不同类型有不同的处理策略,每种消息的处理策略代码都很长,如果都放在这种if else代码快中,代码很难维护也很丑,所以我们一开始就用了策略模式来处理这种情况。

策略模式还挺简单的,就是定义一个接口,然后有多个实现类,每种实现类封装了一种行为。然后根据条件的不同选择不同的实现类。

实现过程
消息对象,当然真实的对象没有这么简单,省略了很多属性

@Data
@AllArgsConstructor
public class MessageInfo {

// 消息类型
private Integer type;
// 消息内容
private String content;

}
1
2
3
4
5
6
7
8
9
10
定义一个消息处理接口

public interface MessageService {

void handleMessage(MessageInfo messageInfo);

}
1
2
3
4
有2个消息处理接口,分别处理不同的消息

处理文本消息

@Service
@MsgTypeHandler(value = MSG_TYPE.TEXT)
public class TextMessageService implements MessageService {

@Override
public void handleMessage(MessageInfo messageInfo) {
    System.out.println("处理文本消息 " + messageInfo.getContent());
}

}
1
2
3
4
5
6
7
8
9
处理图片消息

@Service
@MsgTypeHandler(value = MSG_TYPE.IMAGE)
public class ImageMessageService implements MessageService {

@Override
public void handleMessage(MessageInfo messageInfo) {
    System.out.println("处理图片消息 " + messageInfo.getContent());
}

}
1
2
3
4
5
6
7
8
9
文章写到这,可能大多数人可能会想到要需要如下一个Map, Map<消息类型,消息处理对象>,这样直接根据消息类型就能拿到消息处理对象,调用消息处理对象的方法即可。我们就是这样做的,但是我们不想手动维护这个Map对象,因为每次增加新的消息处理类,Map的初始化过程就得修改

我们使用了注解+ApplicationListener来保存这种映射关系,来看看怎么做的把

定义一个消息类型的枚举类

public enum MSG_TYPE {

TEXT(1, "文本"),
IMAGE(2, "图片"),
VIDEO(3, "视频");

public final int code;
public final String name;

MSG_TYPE(int code, String name) {
    this.code = code;
    this.name = name;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
定义一个注解

@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MsgTypeHandler {

MSG_TYPE value();

}
1
2
3
4
5
6
7
8
不知道你注意到了没,前面的代码中,每种消息处理类上面都有一个@MsgTypeHandler注解,表明了这个处理类
处理哪种类型的消息

@Service
@MsgTypeHandler(value = MSG_TYPE.TEXT)
public class TextMessageService implements MessageService {

@Override
public void handleMessage(MessageInfo messageInfo) {
    System.out.println("处理文本消息 " + messageInfo.getContent());
}

}
1
2
3
4
5
6
7
8
9
用一个context对象保存了消息类型->消息处理对象的映射关系

@Component
public class MessageServiceContext {

private final Map<Integer, MessageService> handlerMap = new HashMap<>();

public MessageService getMessageService(Integer type) {
    return handlerMap.get(type);
}

public void putMessageService(Integer code, MessageService messageService) {
    handlerMap.put(code, messageService);
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
最精彩的部分到了

@Component
public class MessageServiceListener implements ApplicationListener {

@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
    Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(MsgTypeHandler.class);
    MessageServiceContext messageServiceContext = event.getApplicationContext().getBean(MessageServiceContext.class);
    beans.forEach((name, bean) -> {
        MsgTypeHandler typeHandler = bean.getClass().getAnnotation(MsgTypeHandler.class);
        messageServiceContext.putMessageService(typeHandler.value().code, (MessageService) bean);
    });
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
在spring的启动过程中,通过解析注解,将消息类型->消息处理对象的映射关系保存到MessageServiceContext对象中

@Autowired
MessageServiceContext messageServiceContext;

@Test
public void contextLoads() {
// 构建一个文本消息
MessageInfo messageInfo = new MessageInfo(MSG_TYPE.TEXT.code, “消息内容”);
MessageService messageService = messageServiceContext.getMessageService(messageInfo.getType());
// 处理文本消息 消息内容
// 可以看到文本消息被文本处理类所处理
messageService.handleMessage(messageInfo);
}
1
2
3
4
5
6
7
8
9
10
11
12
测试类正常工作,通过策略模式避免了写大量的if else代码,也更容易维护

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值