接口、抽象类、多态这些JAVA基础中的基础,在多少初级中级攻城狮的眼中如同鸡肋,去掉接口其它两项工作两年没真正去使用过的人不在少数。
随着敏捷模式在国内大肆推广,底层技术人员疲于应付不断变动需求,总在高呼红烧产品,清蒸设计。同时为自己那杂乱无章满是补丁的代码找了一个冠冕堂皇的理由——需求一直在变哪有时间去优化!
推荐一本书 Martin Fowler的《重构:改善既有代码的设计》,我感觉写的棒极了,让我认识到什么是重构,什么时候重构,在什么地方重构。(好像跑题了这些跟工厂模式有个球关系?)
重新回到我们本次的案例需求,就以订单状态变更这个业务来说吧,订单变成任意一个状态其实都有着各自不同的业务需求,可他们又有着一些共同的逻辑,
例如(假想案例而已请勿较真):
package com.zhibo.test.service;
public interface OrderStatusService {
/**
* 状态变更业务
* @param orderId 这个参数正常业务肯定是传一个对象了
*/
void orderStatusChange(String orderId);
/**
* 实例所支持的状态类型
* @return
*/
String getType();
}
主要用于定义整个业务流程线,同时实现部分共用的逻辑代码
package com.zhibo.test.service.impl;
import com.zhibo.test.service.OrderStatusService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public abstract class AbstractOrderStatusService implements OrderStatusService {
protected static Logger log = LoggerFactory.getLogger(AbstractOrderStatusService.class);
@Override
public void orderStatusChange(String orderId) {
verify(orderId);
Object obj = new Object();
buildOrder(obj);
// 公共业务 如组装数据修改订单表参数,插入订单状态变更轨迹...
try {
sendMessage(getMessage(null));
} catch (Exception e) {
log.error("update loan status push error: ", e);
}
}
// 用于不同的业务流程可能有特定的数据需要组装
protected void buildOrder(Object obj){}
// 业务前的校验
protected void verify(String orderId){}
protected void sendMessage(Object obj) throws Exception{
if (obj !=null){
// ....调用接口发送消息
}
}
// 根据业务自行组装消息对象
protected abstract Object getMessage(Object dto);
}
各个实例只需要关注差异流程进行补充
package com.zhibo.test.service.impl;
import org.springframework.stereotype.Service;
@Service
public class OrderStatusCanceledServiceImpl extends AbstractOrderStatusService{
@Override
public String getType() {
return "canceled";
}
@Override
protected void buildOrder(Object obj) {
}
@Override
protected void verify(String orderId) {
log.info("订单取消相关数据校验");
}
@Override
protected Object getMessage(Object dto) {
return null;
}
}
package com.zhibo.test.service.impl;
import org.springframework.stereotype.Service;
@Service
public class OrderStatusCloseServiceImpl extends AbstractOrderStatusService{
@Override
public String getType() {
return "close";
}
@Override
protected void buildOrder(Object obj) {
super.buildOrder(obj);
}
@Override
protected void verify(String orderId) {
log.info("订单关闭相关数据校验");
}
@Override
protected Object getMessage(Object dto) {
return null;
}
}
package com.zhibo.test.service.impl;
import org.springframework.stereotype.Service;
@Service
public class OrderStatusTimeoutServiceImpl extends AbstractOrderStatusService{
@Override
public String getType() {
return "timeout";
}
@Override
protected void buildOrder(Object obj) {
super.buildOrder(obj);
}
@Override
protected void verify(String orderId) {
log.info("订单超时相关数据校验");
}
@Override
protected Object getMessage(Object dto) {
return null;
}
}
package com.zhibo.test.method;
import com.zhibo.test.service.OrderStatusService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
public class OrderStateMethodConfiguration {
private Map orderStatusServiceHashMap = new HashMap<>();
@Autowired
private List orderStatusServices;
@PostConstruct
public void init() {
orderStatusServices.forEach(orderStatusService ->
orderStatusServiceHashMap.put(orderStatusService.getType(),orderStatusService));
}
public OrderStatusService getLoanStatusService(String orderState){
return orderStatusServiceHashMap.get(orderState);
}
}
package com.zhibo.test.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TestService {
@Autowired
private OrderStateMethodConfiguration orderStateMethodConfiguration;
public void test(){
orderStateMethodConfiguration.getLoanStatusService("timeout").orderStatusChange("123456");
}
}
输出结果
就这么简单,根据业务实际情况来使用抽象类 结合工厂让你的代码变得简洁易懂,且具备良好的扩展性,总比你在一个方法中写着无数的if判断来区分有逼格。
扩展案例:例如微信扫码登录、手机号短信登录、账户密码登录、第三方登录,类似于这种都需要做参数校验,但是不同的登录方式校验的数据会有一些区别,这时候去定义一个参数校验接口,然后去实现它每一个实例去做一种校验,然后根据登录类型将对应的校验方式放入集合中,工厂返回一个service的集合去循环做校验。
下面有部分代码图