hi,本篇将为您介绍到策略模式+工厂模式在多个场景中的使用。
在网上浏览过很多设计模式文章,都是以基础的实现为例介绍了用法。
在这里,作者将以实战型开放接口的统一入口的场景实现代码来说明白策略模式+工厂模式的无尽用法。
工厂模式:顾名思义就是像现实生活中的工厂,有工人及流水线。将复杂的实现拆分为一条条相应的流水线及专门负责的工人,重复执行,达到最高效率。
策略模式:在我们生活中常见的超市的活动,如打折、满减、买一送一、积分兑换等等活动实现商品最大化销售的方式叫策略模式,这种模式的精髓就是我提前设计了很多种活动,情人节适合用哪一种 我直接上新告示牌即可。
好了,废话不多说,上代码。
我们先做一个统一入口,入参中必须有一个能够在行为上匹配的属性,在这里我们用method属性
统一接口类:入参的对象类型灵活使用,这个选用map
@RestController
@RequestMapping(value = "/api")
public class ApiController {
@PostMapping(value = "/gateway")
public String gateway(@RequestBody Map params) {
// 最朴实无华的参数校验
String method = params.get("method").toString();
if(StrUtil.isEmpty(method)) {
return "fail";
}
BaseService service = ApiConfig.getBaseService(method);
if(ObjectUtil.isNull(service)) {
return "没找到对应的method";
}
return service.execute();
}
}
Method注解:该注解用在后续接口的实现类中,入口的method属性会去核心类中找对应注解的实现类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Method {
String name() default "";
}
核心类:策略模式+简单工厂
自由发挥,必须通过spring上下文中拿到到接口实现类。时间有限,不做封装,以实现为目的,快乐助人。
@Configuration
public class ApiCoreFactory {
/** 工厂对象 */
public static Map<String, BaseService> BASESERVICE_FACTORY;
@Bean
public ApplicationContext setBaseServiceBeanFactory(ApplicationContext context) {
// 从上下文中提取实现BaseService的实现类(必须含有@Service这类会触发bean注册的注解)
Map<String, BaseService> beans = context.getBeansOfType(BaseService.class);
// 单例设计,初始化map拓展大小
if(ObjectUtil.isNull(BASESERVICE_FACTORY)) {
BASESERVICE_FACTORY = new HashMap<>(beans.size());
}
for(Map.Entry<String, BaseService> entry : beans.entrySet()) {
// 有method注解才进行装载
Method method = entry.getValue().getClass().getAnnotation(Method.class);
if(ObjectUtil.isNotNull(method)) {
BASESERVICE_FACTORY.putIfAbsent(method.name(), entry.getValue());
}
}
return context;
}
/**
* 从工厂对象中提取BaseService
* @param method
* @return
*/
public static BaseService getBaseService(String method) {
return BASESERVICE_FACTORY.get(method);
}
}
公共接口
所有的method 实现类都将实现该接口,因为上面从上下文中获取的bean是以实现BaseService的。
public interface BaseService {
String execute();
}
实现类:都是测试实现类,注意return的字符串值,有one,two,three三个不同实现类的返回值。
都必须实现method注解且赋值,上面统一入口的method属性会根据在实现类中的method进行匹配
@Method(name = "one")
@Service
public class OneServiceImpl implements BaseService {
@Override
public String execute() {
return "one";
}
}
@Method(name = "two")
@Service
public class TwoServiceImpl implements BaseService {
@Override
public String execute() {
return "two";
}
}
@Method(name = "three")
@Service
public class ThreeServiceImpl implements BaseService {
@Override
public String execute() {
return "three";
}
}
从上面可以看出来,我们不同于过去的统一入口中有n个if else判断,即以策略+工厂模式实现的更简洁的落地代码。
咱们用postman测试下效果
第一次测试,method=one,成功匹配并返回该实现类的one字符串
第二次测试,method=three
第三次测试,method=four,因为没有在统一入口匹配到该method,返回了“没找到对应的method”
以上即为本篇全部内容,码友们灵活应用各个设计模式,不喜勿喷!