接到一个任务,需求是用策略模式,编写保存接口。
该接口是在springboot上进行开发,我的设想就是该接口接收json数据,其中有表名字段,通过表名来选择不同的策略。后期如果有不同的开发者需要不同的保存策略(往不同的表上保存数据),则只需要写一个实现基础策略的类然后自定义自己的需求即可。(下图框框内的三个类)
其中的返回格式ResponseResult自定义,不需要和我一样。AddService将所有实现了基础策略接口的类都注入Map容器中,并提供根据表名到map中获取策略的方法getResource()。
@RestController
@RequestMapping("/erpAdd")
public class AddController {
@Autowired
private AddService addService;
@RequestMapping("/add")
public ResponseResult add(@RequestBody String parJson){
ResponseResult res = new ResponseResult();
JSONObject data = JSONObject.parseObject(parJson);
String dbName = data.getString("dbName");
JSONObject parJson1 = data.getJSONObject("parJson");
if(parJson.isEmpty()||dbName.isEmpty()){//参数校验
res.setData("");
res.setErrcode(1);
res.setErrmsg("参数不能为空!");
return res;
}
dbName = dbName.toLowerCase();
try {
addService.getResource(dbName,parJson1);
res.setData("");
res.setErrcode(0);
res.setErrmsg("保存成功!");
}catch (Exception e){
res.setData("");
res.setErrcode(1);
res.setErrmsg("保存失败!");
}
return res;
}
}
/**
* 上下文Context,将所有的策略类都注入到map中,
*/
@Service
public class AddService {
//使用线程安全的ConcurrentHashMap 公共接口
private final Map<String, AddStrategy > strategyMap = new ConcurrentHashMap<>();
//Autowired注解会自动将实现策略接口的 实现类注入到Map中,key就是自定义的Bean的名称,对应的是表名
//spring容器会在类加载后自动注入这个方法的参数,并执行一遍方法。
@Autowired
public AddService(Map<String, AddStrategy > strategyMap){
this.strategyMap.clear();
strategyMap.forEach((k,v)-> this.strategyMap.put(k,v));//将所有的策略暴露出来
//将key(即具体策略类中的component的名称)与具体策略类put到map中
}
public void getResource(String dbName, JSONObject parJson) throws Exception {
strategyMap.get(dbName).add(parJson);
//在map中根据表名找的对应的容器
}
}
@Autowired作用在方法上,会在spring初始化后执行一次。lambda表达式中的 k 就是以下"具体策略类" @Component(“wdddb”) 中定义的名称。v 就是具体的策略类。
/**
* 策略接口
*/
public interface AddStrategy {
public void add(JSONObject parJson) throws Exception;
}
在这里插入代码片
/**
* 具体策略类
*
*/
@Component("wdddb")//注入spring中,容器统一管理,直接用表名做容器的名称,通过不同的表名调用具体的策略
public class WdddStrategy implements AddStrategy {
@Autowired
AddMapper addMapper;
@Override
@Transactional(timeout = 25, propagation = Propagation.REQUIRED)
public void add(JSONObject parJson) throws Exception {
String buyerNick = parJson.getString("buyer_nick");
String title = parJson.getString("title");
String type = parJson.getString("type");
if("".equals(buyerNick)||"".equals(title)||"".equals(type)){//parJson必填字段校验
throw new Exception();//有空字段,则抛给上一个
}
Wdddb wdddb = new Wdddb();
wdddb.setBuyer_nick(buyerNick);
wdddb.setTitle(title);
wdddb.setType(type);
addMapper.addWddd(wdddb);
}
}
@Mapper
public interface AddMapper {
void addWddd(@Param("wdddb")Wdddb wdddb);
void addWdddmx(@Param("wdddmxb")Wdddmxb wdddmxb);
}
AddMapper.xml就不赘述了。其他的具体策略类也不写了。
参考:策略设计模式
示例代码
参考中的示例是要用new来实例化的,但是spring的IOC已经将对象的创建交给容器负责了,再使用老方法就是回去了。所以在AddService中把具体策略类的创建交给容器去创建,解耦,易扩展。但是也有缺点,就是需要把所有的具体策略都暴露出来。在小项目中用更加繁琐,只有在大项目多人协助开发的情况下,优点才有所体现。