因为,最近在做excle的导入导出,发现有一个模块地下有14个需要导入导出的类,思来想去用策略+简单工厂模式去除if else if ....,是该模块能更好的维护。带着这样的想法,便在度娘搜了下策略+工厂模式的实现,最后参考了这位老哥的https://www.cnblogs.com/huangqingshi/p/10344265.html文章,
先附上代码:
1.定义一个导入导出的接口:
public interface ExcelOperationStrategy {
void importExcel(InputStream inputstream,ImportParams params);
void exportExcel(String id);
}
2.创建一个策略工厂:
@Autowired
Map<String, ExcelOperationStrategy> strategys = new ConcurrentHashMap<>(14);
3.实现接口
@Component("test")
public class StrategyTest implements ExcelOperationStrategy {
//省略了大部门代码
@Override
public void importExcel(InputStream inputstream, ImportParams params) {
long start1 = System.currentTimeMillis();
do samething
}
@Override
public void exportExcel(String id) {
Error error = errorMapper.selectByPrimaryKey(id);
if (StringUtils.isNotEmpty(error.getContent00())) {
List<TestEntity> list = new ArrayList<>();
list = JSONObject.parseArray(error.getContent00(), TestEntity.class);
FileWithExcelUtil.exportExcel(list, "测试表", "测试", TestEntity.class, "测试表.xls", response);
}
}
}
@Component("test1")
public class StrategyTest1 implements ExcelOperationStrategy {
//省略了大部门代码
@Override
public void importExcel(InputStream inputstream, ImportParams params) {
long start1 = System.currentTimeMillis();
do samething
}
@Override
public void exportExcel(String id) {
Error error = errorMapper.selectByPrimaryKey(id);
if (StringUtils.isNotEmpty(error.getContent00())) {
List<Test1Entity> list = new ArrayList<>();
list = JSONObject.parseArray(error.getContent00(), Test1Entity.class);
FileWithExcelUtil.exportExcel(list, "测试表1", "测试1", Test1Entity.class, "测试表1.xls", response);
}
}
}
@Component("test2")
public class StrategyTest2 implements ExcelOperationStrategy {
//省略了大部门代码
@Override
public void importExcel(InputStream inputstream, ImportParams params) {
long start1 = System.currentTimeMillis();
do samething
}
@Override
public void exportExcel(String id) {
Error error = errorMapper.selectByPrimaryKey(id);
if (StringUtils.isNotEmpty(error.getContent00())) {
List<Test1Entity> list = new ArrayList<>();
list = JSONObject.parseArray(error.getContent00(), Test2Entity.class);
FileWithExcelUtil.exportExcel(list, "测试表2", "测试1", Test2Entity.class, "测试表2.xls", response);
}
}
}
..........
4.controller实现
@RequestMapping(value = "uploadfile", method = RequestMethod.POST)
@ResponseBody
public AjaxResponse uploadfile(@RequestParam("file") MultipartFile file,String type) {
long startTime = System.currentTimeMillis();
System.out.println("--------------------startTime------------------------------" + startTime);
ImportParams params = new ImportParams();
params.setHeadRows(1);
params.setTitleRows(0);
try {
factoryForStrategy.getStrategy(type).importExcel(file.getInputStream(),params);
} catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("--------------------endtime------------------------------");
long endtime = System.currentTimeMillis() - startTime;
long minutes = (endtime / 1000) / 60;
long seconds = (endtime / 1000) % 60;
System.out.format("%d 毫秒 = %d 分钟 又 %d 秒.", endtime, minutes, seconds);
}
return AjaxResponse.success("导入数据成功!");
}
其中我对
@Autowired
Map<String, ExcelOperationStrategy> strategys = new ConcurrentHashMap<>(14);为什么可以通过传一个bean名称,智能的调用相应的类方法呢?
首先通过查看@Autowired源码发现有这么一段话:
<p>In case of a {@link java.util.Collection} or {@link java.util.Map}
dependency type, the container will autowire all beans matching the
declared value type. In case of a Map, the keys must be declared as
type String and will be resolved to the corresponding bean names
大体上意思是对于CollectionMap的依赖类型,容器会自动装配所有与声明值类型匹配的bean。如果是Map,key必须是String类型,并将解析为相应的bean名称,value为相应的bean。
话不都说,上代码测试一下。
定义接口
public interface IAnimal {
void eat();
}
@Component("cat")
public class Cat implements IAnimal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
@Component("dog")
public class Dog implements IAnimal {
@Override
public void eat() {
System.out.println("狗啃骨头");
}
}
@Component("sheep")
public class Sheep implements IAnimal {
@Override
public void eat() {
System.out.println("羊吃青草");
}
}
注入
@Service
public class AnimalService {
@Autowired
List<IAnimal> animalList;
@Autowired
Map<String, IAnimal> animalMap;
public void test() {
System.out.println("--------------list:----------------");
for (IAnimal iAnimal : animalList) {
iAnimal.eat();
}
System.out.println("-------------------list end");
System.out.println("---------------------map:--------------");
for (Map.Entry<String, IAnimal> entry : animalMap.entrySet()) {
System.out.println("Map:" + entry.getKey() + ", " + entry.getValue());
}
}
public void testEat(String key) {
IAnimal iAnimal = animalMap.get(key);
if (null != iAnimal) {
iAnimal.eat();
}
}
}
测试一波:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class);
ApplicationContext context=springApplication.run(args);
AnimalService bean = context.getBean(AnimalService.class);
bean.test();
System.out.println("策略模式测试");
bean.testEat("dog");
}
}
控制台输出:
是不是感觉很神奇!,通过调用不同的实现类,即可达到策略模式的类似效果。