与其在各个抄来抄去的技术博客上看,不如直接看大厂博客,这是我觉得看过整体质量最高的博主了。
设计模式最佳套路1—— 愉快地使用策略模式
原文: 设计模式最佳套路1—— 愉快地使用策略模式 - 知乎
- if-else 不超过 2 层,块中代码 1~5 行,直接写到块中,否则封装为方法
- if-else 超过 2 层,但块中的代码不超过 3 行,尽量使用卫语句
- if-else 超过 2 层,且块中代码超过 3 行,尽量使用策略模式
这里的用法,策略+spring,利用ApplicationContextAware建立工厂,使用时从工厂取即可,dubbo读Reference注解也干了一样的事情。
新建一个springboot工程
类图看一下啊,就是一个策略接口,三个实现类,然后用工厂包策略,利用spring扩展点,在WebApplicationContext initialization completed之后,将上下文给factory,在bean初始化之后,将bean对象加入工厂持有的map中,接口过来就是松耦合的从工厂中获取相应的handler,执行handlerSubmit方法
策略接口:
package com.strategy.demo.strategy;
import com.strategy.demo.strategy.params.CommonPairResponse;
import com.strategy.demo.strategy.params.FormSubmitRequest;
import java.io.Serializable;
public interface FormSubmitHandler<T extends Serializable>{
String getSubmitType();
CommonPairResponse<String,T> handleSubmit(FormSubmitRequest request);
}
策略实现类:
package com.strategy.demo.strategy.Impl;
import com.strategy.demo.strategy.params.CommonPairResponse;
import com.strategy.demo.strategy.FormSubmitHandler;
import com.strategy.demo.strategy.params.FormSubmitRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.ArrayList;
@Component
public class FormHsfSubmitHandler implements FormSubmitHandler<Serializable> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public String getSubmitType() {
return "hsf";
}
@Override
public CommonPairResponse<String, Serializable> handleSubmit(FormSubmitRequest request) {
logger.info("HSF 模式提交:userId={}, formInput={}", request.getUserId(), request.getFormInput());
// 进行 HSF 泛化调用,获得业务方返回的提示信息和业务数据
Object data = hsfSubmitData(request);
CommonPairResponse<String, Serializable> response = CommonPairResponse.success("HSF 模式提交成功!", data);
return response;
}
private Object hsfSubmitData(FormSubmitRequest request) {
ArrayList<Long> result = new ArrayList<>();
result.add(165L);
return result;
}
}
package com.strategy.demo.strategy.Impl;
import com.strategy.demo.strategy.params.CommonPairResponse;
import com.strategy.demo.strategy.FormSubmitHandler;
import com.strategy.demo.strategy.params.FormSubmitRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class FormModelSubmitHandler implements FormSubmitHandler<Long> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public String getSubmitType() {
return "model";
}
@Override
public CommonPairResponse<String, Long> handleSubmit(FormSubmitRequest request) {
logger.info("模型提交:userId={}, formInput={}", request.getUserId(), request.getFormInput());
// 模型创建成功后获得模型的 id
Long modelId = createModel(request);
return CommonPairResponse.success("模型提交成功!", modelId);
}
private Long createModel(FormSubmitRequest request) {
// 创建模型的逻辑
return 123L;
}
}
方法返回:
package com.strategy.demo.strategy.params;
import lombok.Data;
@Data
public class CommonPairResponse<E, T> {
private String returnCode;
private String returnMsg;
private Object data;
public static <E, T> CommonPairResponse success(E e, T t) {
CommonPairResponse<E, T> response = new CommonPairResponse<>();
response.setReturnCode("000000");
response.setReturnMsg(e.toString());
response.setData(t);
return response;
}
public static <E, T> CommonPairResponse failure(T t) {
CommonPairResponse<E, T> response = new CommonPairResponse<>();
response.setReturnCode("999999");
response.setReturnMsg(t.toString());
response.setData(null);
return response;
}
public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
方法请求
package com.strategy.demo.strategy.params;
import lombok.Data;
import java.util.Map;
@Data
public class FormSubmitRequest {
private String submitType;
private Long userId;
private Map<String, Object> formInput;
public String getSubmitType() {
return submitType;
}
public void setSubmitType(String submitType) {
this.submitType = submitType;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
this.userId = userId;
}
public Map<String, Object> getFormInput() {
return formInput;
}
public void setFormInput(Map<String, Object> formInput) {
this.formInput = formInput;
}
}
工厂:
package com.strategy.demo.strategy;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@Component
public class FormSubmitHandlerFactory implements InitializingBean, ApplicationContextAware {
public static final Map<String, FormSubmitHandler<Serializable>> FORM_SUBMIT_HANDLER_MAP
= new HashMap<>(8);
private ApplicationContext appContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.appContext = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
// 将 Spring 容器中所有的 FormSubmitHandler 注册到 FORM_SUBMIT_HANDLER_MAP
appContext.getBeansOfType(FormSubmitHandler.class)
.values()
.forEach(handler -> FORM_SUBMIT_HANDLER_MAP.put(handler.getSubmitType(), handler));
}
}
具体serviceImpl
package com.strategy.demo.service.impl;
import com.strategy.demo.service.FormService;
import com.strategy.demo.strategy.FormSubmitHandler;
import com.strategy.demo.strategy.FormSubmitHandlerFactory;
import com.strategy.demo.strategy.params.CommonPairResponse;
import com.strategy.demo.strategy.params.FormSubmitRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.util.Map;
@Service
public class FormServiceImpl implements FormService {
@Autowired
private FormSubmitHandlerFactory formSubmitHandlerFactory;
@Override
public CommonPairResponse<String, Serializable> submitForm(FormSubmitRequest request) {
String submitType = request.getSubmitType();
Map<String, FormSubmitHandler<Serializable>> formSubmitHandlerMap =
formSubmitHandlerFactory.FORM_SUBMIT_HANDLER_MAP;
FormSubmitHandler<Serializable> handler = formSubmitHandlerMap.get(submitType);
if (handler == null) {
return CommonPairResponse.failure("非法的提交类型: " + submitType);
}
CommonPairResponse<String, Serializable> response = handler.handleSubmit(request);
return response;
}
}
测试一下
提交非法类型时:
OK
以上算是复现完了,再做一下课外作业:
这是xxl-rpc里关于扫描被@XxlRpcService注解的类
package com.xxl.rpc.core.remoting.provider.impl;
import com.xxl.rpc.core.remoting.provider.XxlRpcProviderFactory;
import com.xxl.rpc.core.remoting.provider.annotation.XxlRpcService;
import com.xxl.rpc.core.util.XxlRpcException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.Map;
/**
* xxl-rpc provider (for spring)
*
* @author xuxueli 2018-10-18 18:09:20
*/
public class XxlRpcSpringProviderFactory extends XxlRpcProviderFactory implements ApplicationContextAware, InitializingBean,DisposableBean {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, Object> serviceBeanMap = applicationContext.getBeansWithAnnotation(XxlRpcService.class);
if (serviceBeanMap!=null && serviceBeanMap.size()>0) {
for (Object serviceBean : serviceBeanMap.values()) {
// valid
if (serviceBean.getClass().getInterfaces().length ==0) {
throw new XxlRpcException("xxl-rpc, service(XxlRpcService) must inherit interface.");
}
// add service
XxlRpcService xxlRpcService = serviceBean.getClass().getAnnotation(XxlRpcService.class);
String iface = serviceBean.getClass().getInterfaces()[0].getName();
String version = xxlRpcService.version();
super.addService(iface, version, serviceBean);
}
}
// TODO,addServices by api + prop
}
@Override
public void afterPropertiesSet() throws Exception {
super.start();
}
@Override
public void destroy() throws Exception {
super.stop();
}
}
有没有发现什么相同不同
如果你想加入一个其他的strategy,可以直接面向接口编程,而不需要修改任何的原有类,符合设计模式基本原则
以上。