一,业务场景
消息下发到订单系统,不同的消息代表不同的订单业务逻辑
二,业务设计思路
1.关于消息:应该统一个格式,比如消息是xml或者json,应该定义统一的消息结构,方便后续统一解析处理
2.相同的处理逻辑:拿到消息后,需要统一解析处理,解析出核心业务消息体,传入相应业务处理逻辑
3.不同的逻辑:不同的消息,对应不同的业务处理逻辑
4.怎么区分不同的消息:发送消息时,定义一个参数如:tags,区分不同的业务消息
5.不同的消息怎么进入对应的业务处理中:根据tags,取到实现类
三,代码设计思路
代码:
1.接口
public interface BmsService {
boolean execute(EccMessageReqVO eccMessageReqVO) throws Exception;
BmsServiceEnum getType();
}
2.抽象类
@Component
@Slf4j
public abstract class AbstractBmsService implements BmsService {
private static final String SHEET = "SHEET";
@Override
@Transactional
public boolean execute(EccMessageReqVO eccMessageReqVO) throws Exception {
log.info("执行ecc-bms-mq消费消息service:{},入参:{}", eccMessageReqVO.getEccServiceName(),
JSON.toJSONString(eccMessageReqVO));
String message = eccMessageReqVO.getMessage();
// JSONObject obj = JSON.parseObject(message).getJSONObject(SHEET);
// if (Objects.nonNull(obj)) {
// String msg = JSON.toJSONString(obj);
// eccMessageReqVO.setMessage(msg);
// }
this.process(eccMessageReqVO);
return true;
}
public abstract void process(EccMessageReqVO eccMessageReqVO) throws Exception;
}
3.实现类
@Service
@Slf4j
public class ECCBMS152ServiceImpl extends AbstractBmsService {
@Override
public void process(EccMessageReqVO eccMessageReqVO) throws Exception {
String msaage = eccMessageReqVO.getMessage();
log.info("ECCBMS152 message: {}", msaage);
return;
}
@Override
public BmsServiceEnum getType() {
return BmsServiceEnum.ECC_BMS152;
}
}
设计模式:策略 +工厂+模板
类与接口:
一个接口:抽象类实现该接口,接口中包含两个方法,模板方法:抽象类实;区分不同业务类方法:子类实现
一个抽象类:解决上述2.3问题,共同的解析逻辑在抽象类中公共方法实现,定义一个抽象接口由不同业务实现类实现。方法:模板方法:处理共同逻辑; 抽象方法:子类实现
多个业务实现类:解决上述3,5问题,继承抽象类,实现抽象类中抽象方法:实现自己的业务;实现接口中方法:标记实现类本身,用于后续获取具体实现类
设计模式体现:
1.模板方法模式:抽象类:模板方法实现公共逻辑,抽象方法实现具体逻辑,
2.策略模式:定义一个接口,不同子类实现自己类型逻辑
3.抽象工厂:实现自己类型逻辑模型,也可以理解为抽象工厂。与策略很相似
抽象工厂简介:
抽象工厂模式同工厂方法模式一样,也是由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。现在我们来分析其基本结构和实现方法。
抽象工厂模式的主要角色如下。
- 抽象工厂(Abstract Factory):提供了创建产品的接口,它包含多个创建产品的方法 newProduct(),可以创建多个不同等级的产品。
- 具体工厂(Concrete Factory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建。
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品。
- 具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系。
抽象工厂与代码对应关系
1.抽象工厂:对应接口
2.具体工厂:对应实现类
3.抽象产品:对应枚举类,接口中返回的枚举类
public enum BmsServiceEnum implements GenericStringEnum {
ECC_BMS110("ECC_BMS110", "退货申请单上传-生鲜"),
ECC_BMS110A("ECC_BMS110A", "退货申请单上传-食品用品"),
4.具体产品:子类接口中返回的具体商品,如:
public BmsServiceEnum getType() {
return BmsServiceEnum.ECC_BMS152;
}
四,上述第二点业务逻辑中第五点问题具体实现
利用多态,项目启动时,把所有实现类,存储到map中,key:枚举类,value:接口。消息下发时,根据tags取对应枚举,再根据枚举获取对应实现类,执行相应业务逻辑
@Component
public class BmsServiceSelector implements InitializingBean {
private static final Map<BmsServiceEnum, BmsService> serviceMap = new HashMap<>();
@Resource
private List<BmsService> EccServices;
@Override
public void afterPropertiesSet() {
for (BmsService service : EccServices) {
serviceMap.put(service.getType(), service);
}
}
public BmsService getService(BmsServiceEnum bmsServiceEnum) {
if (null == bmsServiceEnum) {
throw new IllegalArgumentException("操作失败!");
}
return serviceMap.get(bmsServiceEnum);
}
}
五,思考
模板与策略区别
1.模板定义的是抽象类,策略定义的是接口
2.与子类关系:
抽象类:子类的执行结果可能返回来影响抽象的中的逻辑,即把子类处理的结果作为抽象类中其他逻辑的参数,进一步处理。
策略:没有上述抽象类,反向影响的逻辑
策略与工厂区别
相同点:都是通过定义接口实现
不同点:工厂涉及抽象产品,具体产品,通过多态体现;策略:上述实现通过枚举体现
理解错误的地方,欢迎留言指正交流,谢谢!