模式定义:使多个对象都有机会处理请求,从而避免了请求者的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。
背景
用户从公司离职时需要转交全部资源,资源多达十几种,这些资源需要用户按照顺序手动一一处理,最近这个页面总是报错,打开代码,原来的代码大概是这样的。
resource1 = ...
resource2 = ...
resource3 = ...
...
resource20 = ...
if (resource1.size() > 0){
// 提供页面信息
// 切换转交资源页面
} else if (){
//.....
}
//...
一个方法写了100多行代码,不易维护和扩展。显然,这样的代码中判断各个资源是否需要处理是顺序的,这样就引入了处理顺序的耦合,如果需要更改转交顺序,那么需要更改代码才能够实现。
定义抽象类LeaveHandler
子类实现是否需要处理以及跳转页面的逻辑
public abstract class LeaveHandler {
public static final String UID = "uid";
public static final String USER_NAME = "userName";
public static final String USER = "user";
public static final String STEP = "step";
public static final String STEPS = "steps";
public static final String PAGE_TIP = "pageTip";
String message;
public abstract boolean needHandle(Map<String, Object> context);
public abstract ModelAndView buildView(Map<String, Object> context) throws Cloud2Exception;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
创建管理类LeaveHandlerChainManager
,在获取在配置中心定义好的离职资源转交顺序,生成责任链
public class LeaveHandlerChainManager {
@Autowired
ConfigCenterService configCenterService;
@Autowired
MachineHandler machineHandler;
@Autowired
ProjectHandler projectHandler;
...
/**
* 虚机
*/
private static final String MACHINE = "machine";
/**
* 项目
*/
private static final String PROJECT = "project";
...
private List<LeaveHandler> defaultLeaveHandlerChain;
@PostConstruct
private void init() {
String[] config = DEFAULT_CONFIG.split(";");
defaultLeaveHandlerChain = buildChain(config);
}
public List<LeaveHandler> buildChain(String[] handlerConfig) {
if (handlerConfig == null || handlerConfig.length == 0) {
return Collections.emptyList();
}
List<LeaveHandler> res = new ArrayList<LeaveHandler>();
for (String config : handlerConfig) {
if (MACHINE.equals(config)) res.add(machineHandler);
else if (PROJECT.equals(config)) res.add(projectHandler);
...
}
return res;
}
public List<LeaveHandler> getLeaveHandlerChain() {
String[] currentConfig = configCenterService.getLeaveStepOrderConfig();
if (currentConfig == null) {
return defaultLeaveHandlerChain;
}
return buildChain(currentConfig);
}
}
在Controller处调用责任链,进行处理
List<LeaveHandler> leaveHandlerChain = leaveHandlerChainManager.getLeaveHandlerChain();
Map<String, Object> context = new HashMap<String, Object>();
context.put(LeaveHandler.STEPS, getStepsFromChain(leaveHandlerChain));
context.put(LeaveHandler.USER, user);
context.put(LeaveHandler.UID, user.getUid());
for (int i = 0; i < leaveHandlerChain.size(); i++) {
LeaveHandler handler = leaveHandlerChain.get(i);
//按节点定义的逻辑判断是否需要处理
boolean need = handler.needHandle(context);
if (need) {
context.put(LeaveHandler.STEP, i + 1);
//进行业务处理
return handler.buildView(context);
}
}
LevelHander
抽象类,实现抽象方法,然后在配置中心配置即可这种将过程化的代码抽象化,用类与类之间的关系来表达其内在联系的方式,提高了代码的可重用和可扩展性。
在离职流程代码中,LeaelHander
就是抽象的体现,其子类的是平行的、互不干扰的解耦的,LeaveHandlerChainManager
是整个离职流程的管理类,通过它能够获得整个链并对它进行处理。