策略类:
public AssetComplexService getService(Integer type) {
if(type == null){
log.error("获取对应实现类失败");
}
strategyMap.put(1,assetReceiveService);
strategyMap.put(2,assetBorrowService);
strategyMap.put(3,assetReturnService);
strategyMap.put(4,assetSendbackService);
return strategyMap.get(type);
}
实现类1:
@Service("assetReceiveService")
public class AssetReceiveServiceImpl extends ServiceImpl<AssetComplexDao, AssetComplexDO> implements AssetComplexService{....}
实现类2:
@Service("assetBorrowService")
public class AssetBorrowServiceImpl extends ServiceImpl<AssetComplexDao, AssetComplexDO> implements AssetComplexService{....}
实现类3:
@Service("assetReturnService")
public class AssetReturnServiceImpl extends ServiceImpl<AssetComplexDao, AssetComplexDO> implements AssetComplexService{....}
实现类4:
@Service("assetSendbackService")
public class AssetSendbackServiceImpl extends ServiceImpl<AssetComplexDao, AssetComplexDO> implements AssetComplexService{....}
controller类:
public class AssetComplexController {
@Autowired
AssetService assetService;
@Autowired
Factory factory;
@ApiOperation("分页列表")
@PostMapping("/list")
public Result<IPage<AssetComplexDO>> list(@RequestBody SearchCommonDTO<?> params, int type){
Result<IPage<AssetComplexDO>> result = new Result<>();
AssetComplexService assetComplexService = factory.getService(type);
result.setResult(assetComplexService.queryPage(params,type));
return result;
}
策略模式自动注入的map:
Map<String,UserService> map;
这里的String怎么优化?
1、用枚举的话,每次新增一个需求还得再更新一些这个枚举类?那就跟一个个put进去一样。
2、每个策略类(实现类)里写一个getUserType方法,但是也得先判断类型才能进入这个策略类(实现类)呀。
新的相同的需求出现的时候,不需要修改我的原有代码(所有),只需新增一个实现类并重写那些方法就行;
传入的type参数为int,而不是String。
万分感谢!
参考springmvc的参数解析器,你的AssetComplexService 加一个boolean support方法,入参就是int type,
这样只要你编码规范,一个type对应一个实现类,这就不需要改任何代码了
可以用枚举实现这种策略模式。
新增策略的时候,只需要新增一个实现类,标识 @Service
注解。再添加一个枚举实例就行。
闲着没事儿,我给你写了一个,你可以参考参考
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
// 任务执行接口
interface TypeService {
Object execute();
}
// 各个实现
@Component
class Type1Service implements TypeService {
@Override
public Object execute() {
return "我是Type1";
}
}
@Component
class Type2Service implements TypeService {
@Override
public Object execute() {
return "我是Type2";
}
}
@Component
class Type3Service implements TypeService {
@Override
public Object execute() {
return "我是Type3";
}
}
@Component
class Type4Service implements TypeService {
@Override
public Object execute() {
return "我是Type4";
}
}
// 策略枚举
enum Type {
Type1(1, Type1Service.class),
Type2(2, Type2Service.class),
Type3(3, Type3Service.class),
Type4(4, Type4Service.class),
;
private Integer value;
private Class<? extends TypeService> handler;
private static Map<Integer, Type> enums = new HashMap<>();
static {
for (Type type : Type.values()) {
if (enums.containsKey(type.value)) {
throw new IllegalArgumentException("重复的value值:" + type.value);
}
enums.put(type.value, type);
}
}
Type(Integer value, Class<? extends TypeService> handler){
this.value = value;
this.handler = handler;
}
public TypeService getService (ApplicationContext applicationContext) {
return applicationContext.getBean(this.handler);
}
public static Type get(Integer value) {
return enums.get(value);
}
}
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private ApplicationContext applicationContext;
@GetMapping(produces = "text/plain; charset=utf-8")
public Object test(@RequestParam("type") Integer val) {
Type type = Type.get(val);
if (type == null) {
return "策略不存在:" + val;
}
TypeService service = type.getService(applicationContext);
if (service == null) {
return "策略没有实现:" + val;
}
return service.execute().toString();
}
}
@Autowired
AssetService assetService;
直接改成
@Autowired
Map<String,AssetService > map;
然后调用就直接map.get(type) 就行了,不需要你的这个Factory ;
注意这样写你原来的
@Service("assetReceiveService")
public class AssetReceiveServiceImpl
就得改成:
@Service("1") // 这个bean的名称自己定义,和map的key对上就行
public class AssetReceiveServiceImpl;
在2楼的基础上修改一下
@RestController
@RequestMapping("/test")
public class testController {
@Autowired
private ApplicationContext applicationContext;
@GetMapping(produces = "text/plain; charset=utf-8")
public Object test(@RequestParam("type") String beanName) {
if (beanName== null) {
return "策略不存在:" + beanName;
}
TypeService service =(TypeService) applicationContext.getBean(beanName);
if (service == null) {
return "策略没有实现:" + beanName;
}
return service.execute().toString();
}
}
@Service
public class Type1Service implements TypeService {
@Override
public Object execute() {
return "我是Type1";
}
}
使用beanName 作为入参就行了 不过测试的时候要注意首字母小写spring 内部好像在注册bean的时候做了处理首字母会变为小写
最近在写设计模式相关的论文,嗯
也有这种想法,我的做法是将map的映射关系交给外部配置文件或者是静态代码。
在新写一个类的时候使反射先加载它,并把它放在容器中。
这样做是不管想减少还是增加都可以。