设计模式之策略模式实现
简介
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。
在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法
场景
假设我们现在有几种情况,处理不同的业务场景,在处理订单情况下,要分别处理不同的订单,
- 处理普通订单
- 处理团购订单
- 处理促销订单
那么如果在以往的编码情况下,在处理很多类型分别处理不同的业务逻辑,这些类型以后可能会持续增加到很多,是一直使用if else,有没有更好的解决办法。现在记录下,学习。
实现思路
定义自定义注解给不同的实现方法定义不同的Bean,通过Spring 初始化去加载这些Bean放在同一个Map列表中,Key是我们定义的注解上面的类型值,Valu就是各自不同的Bean了,根据前端需要不同的结果,返回不同的业务处理的bean。
具体代码实现。
通过使用自定义注解来实现不同的业务逻辑返回不同业务结果
1.先定义一个类的接口实现业务方法
public abstract class AbstractHandler {
abstract public String handle(String name);
}
2.自定义注解
@Target(ElementType.TYPE)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DgbSecurityScannerRegistrar.class)
public @interface HandleType {
String value();
}
3.业务逻辑实现
3.1处理普通订单
@Component
@HandleType(value = "1")
public class NormalHandler extends AbstractHandler {
@Override
public String handle(String name) {
return "处理普通订单";
}
}
3.2处理团购订单
@Component
@HandleType(value = "2")
public class GroupHandler extends AbstractHandler {
@Override
public String handle(String name) {
return "处理团购订单";
}
}
3.3处理促销订单
@Component
@HandleType(value = "3")
public class PromtionHandler extends AbstractHandler {
@Override
public String handle(String name) {
return "处理促销订单";
}
}
4.Spring初始化扫描自定义注解注入我们定义的Bean
4.1定义HandlerProcessor去实现SpringBeanFactoryPostProcessor的方法
@Component
@SuppressWarnings("unchecked")
public class HandlerProcessor implements BeanFactoryPostProcessor {
/**
* 扫描包路径,自己封装的业务处理的不同的结果
*/
private static final String HANDLER_PACKAGE = "com.example.demo.configuration.handle";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, Class> handlerMap = Maps.newHashMapWithExpectedSize(3);
// ClassScaner 扫描包下的bean
ClassScaner.scan(HANDLER_PACKAGE, HandleType.class).forEach(clazz -> {
// 获取注解中的类型值
String type = clazz.getAnnotation(HandleType.class).value();
// 将注解中的类型值作为key,对应的类作为value,保存在Map中
handlerMap.put(type, clazz);
});
// 初始化HandlerContext,将其注册到spring容器中
HandlerContext context = new HandlerContext(handlerMap);
beanFactory.registerSingleton(HandlerContext.class.getName(), context);
}
}
4.1.1附带ClassScaner实现代码
public class ClassScaner implements ResourceLoaderAware {
private final List<TypeFilter> inClueFilter = new LinkedList<>();
private final List<TypeFilter> exClueFilter = new LinkedList<>();
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
@SafeVarargs
public static Set<Class<?>> scan(String[] basePackages, Class<? extends Annotation>... annotation) {
ClassScaner classScaner = new ClassScaner();
if (ArrayUtils.isNotEmpty(annotation)) {
for (Class<? extends Annotation> anno : annotation) {
classScaner.andInClueFilter(new AnnotationTypeFilter(anno));
}
}
Set<Class<?>> classes = new HashSet<>();
for (String basePackage : basePackages) {
classes.addAll(classScaner.doScan(basePackage));
}
return classes;
}
@SafeVarargs
public static Set<Class<?>> scan(String basePackages, Class<? extends Annotation>... annotation) {
return ClassScaner.scan(StringUtils.tokenizeToStringArray(basePackages,",; \t\n"),annotation);
}
public ResourceLoader gerResourceLoader() {
return resourcePatternResolver;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourcePatternResolver=ResourcePatternUtils.
getResourcePatternResolver(resourceLoader);
this.metadataReaderFactory=new CachingMetadataReaderFactory(
resourceLoader);
}
public MetadataReaderFactory getMetadataReaderFactory() {
return metadataReaderFactory;
}
public void setMetadataReaderFactory(MetadataReaderFactory metadataReaderFactory) {
this.metadataReaderFactory = metadataReaderFactory;
}
private Set<Class<?>> doScan(String basePackage) {
Set<Class<?>> classes = new HashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.
resolvePlaceholders(basePackage))
+ "/**/*.class";
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
for (int i = 0; i < resources.length; i++) {
Resource resource = resources[i];
if (resource.isReadable()){
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
if (inClueFilter.size()==0||exClueFilter.size()==0||mathes(metadataReader)){
classes.add(Class.forName(metadataReader
.getClassMetadata().getClassName()));
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return classes;
}
private boolean mathes(MetadataReader metadataReader) throws IOException {
for (TypeFilter typeFilter : this.exClueFilter) {
if (typeFilter.match(metadataReader,this.metadataReaderFactory)){
return false;
}
}
for (TypeFilter typeFilter : this.inClueFilter) {
if (typeFilter.match(metadataReader,this.metadataReaderFactory)){
return true;
}
}
return false;
}
private void andInClueFilter(TypeFilter inClueFilter) {
this.inClueFilter.add(inClueFilter);
}
public void addExClueFilter(TypeFilter inClueFilter) {
this.exClueFilter.add(0,inClueFilter);
}
public void restFilters(boolean userDefaultFilters){
this.inClueFilter.clear();
this.exClueFilter.clear();
}
4.1.1附带HandlerContext 实现代码
public class HandlerContext {
private Map<String, Class> handlerMap;
public HandlerContext(Map<String, Class> handlerMap) {
this.handlerMap = handlerMap;
}
public AbstractHandler getInstance(String type) {
Class clazz = handlerMap.get(type);
if (clazz == null) {
throw new IllegalArgumentException("not found handler for type: " + type);
}
return (AbstractHandler) BeanTool.getBean(clazz);
}
}
5.注入HandlerContextBean实现业务处理
5.1 Service实现
@Service()
public class AreaServiceImpl extends ServiceImpl<AreaMapper, Area> implements IAreaService {
@Autowired
private HandlerContext handlerContext;
@Override
public String handle(String type) {
AbstractHandler instance = handlerContext.getInstance(type);
return instance.handle(type);
}
}
5.2 Controlle实现
@RestController
@RequestMapping("/area")
public class AreaController {
@Autowired
private IAreaService areaService;
@RequestMapping(value = "/test")
public String handel(String type){
return areaService.handle(type);
}
}
梳理不易,请多多支持