microblog | 微博客
原创
访问
0
获赞
0
评论
相关推荐
暂无数据
最新文章
暂无数据
热门文章
暂无数据

Java使用策略模式+工厂模式优化if else 代码

写完bug就找女朋友 2023年08月19日 15:21:22 424 701 0
分类专栏: Java JavaWeb Java工具 文章标签: 消除if else 工厂模式

一、问题描述

if else if是代码中经常要用的语句块,如果选择分支不多的话还好,当时当选择分支很多的时候,就不能再这样做了;那么有什么办法可以优化多个选择分支结构呢?

需求如下所示:

/** * 根据文件路径读取文件内容 * @param path FilePath * @return ReadFileResultVO */ public ReadFileResultVO ReadFile(String path) { if () {//如果是DOC类型的文件,则调用读取DOC文件的方法 } else if () {//如果是DOCX类型的文件,则调用读取DOCX文件的方法 } else if () {//如果是PDF类型的文件,则调用读取PDF文件的方法 } else if () {//如果是OFD类型的文件,则调用读取OFD文件的方法 } .......... }

二、解决办法

当选择结构过多时,就不再适用于if else方法了,此时我们可以使用设计模式中的策略模式+工厂模式优化if else语句块.

总体结构如下:

image.png

三、具体实现

  1. 总接口 ReadFileUtil.java
import com.xxx.utils.factory.api.IReadFileHandleStrategy; import com.xxx.vo.ReadFileResultVO; /** * 工厂模式下的读取文件 * @author wxz * @date 2023.4.12 * @version 1.0.0 */ public class ReadFileUtil { /** * 根据绝对路径读取文件 * @param fileAbsolutePath 文件的绝对路径 * @return 读取结果VO */ public ReadFileResultVO readFileByAbsolutePath(String fileAbsolutePath){ //策略上下文 ReceiptStrategyContext receiptStrategyContext = new ReceiptStrategyContext(); // String fileAbsolutePath = "E:\\desktop\\一线楼市城市投资指南.docx"; IReadFileHandleStrategy readFileHandleStrategy = ReadFileHandleStrategyFactory.getReadFileHandleStrategy(fileAbsolutePath); receiptStrategyContext.setReadFileHandleStrategy(readFileHandleStrategy); //执行策略 return receiptStrategyContext.handleReadFile(fileAbsolutePath); } }
  1. 策略上下文 ReadFileStrategyContext.java
import com.xxx.utils.factory.api.IReadFileHandleStrategy; import com.xxx.vo.ReadFileResultVO; /** * * @author wxz * @date 2023.4.12 * @version 1.0.0 */ public class ReadFileStrategyContext{ private IReadFileHandleStrategy readFileHandleStrategy; /** * 设置策略接口 * @param readFileHandleStrategy 策略标头 */ public void setReadFileHandleStrategy(IReadFileHandleStrategy readFileHandleStrategy) { this.readFileHandleStrategy = readFileHandleStrategy; } public ReadFileResultVO handleReadFile(String filePath){ if (readFileHandleStrategy != null) { return readFileHandleStrategy.handleReadFile(filePath); } return new ReadFileResultVO(); } }
  1. 文件类型枚举UploadFileTypeEnum.java
/** * 文件上传所支持的类型 */ public enum UploadFileTypeEnum { TXT(0, "TXT"), ODF(1, "OFD"), DOC(2, "DOC"), DOCX(3,"DOCX"), WPS(4,"WPS"), PDF(5,"PDF"); private Integer value; private String type; UploadFileTypeEnum(Integer value, String type) { this.value = value; this.type = type; } public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } public String getType() { return type; } public void setType(String type) { this.type = type; } }
  1. 策略工厂 ReadFileHandleStrategyFactory.java
import com.xxx.common.exception.ServiceException; import com.xxx.common.utils.StringUtils; import com.xxx.constant.enums.UploadFileTypeEnum; import com.xxx.utils.factory.api.IReadFileHandleStrategy; import com.xxx.utils.factory.impl.ReadFileFactory; import java.util.HashMap; import java.util.Map; /** * @Description: 根据文件类型调用读取方法的策略工厂 * @Auther: wxz */ public class ReadFileHandleStrategyFactory { private static Map<String, IReadFileHandleStrategy> readFileHandleStrategyMap = new HashMap<>();; /** * 策略工厂,有扩展方法时,在工厂put进去 */ static { ReadFileFactory factory = new ReadFileFactory(); //ReadDOCFileStrategy 方法属于 ReadFileFactory类下面的非静态方法,因此需要第二次new即 factory.new ReadDOCFileStrategy(),而不能直接new readFileHandleStrategyMap.put(UploadFileTypeEnum.DOC.getType(), factory.new ReadDOCFileStrategy()); readFileHandleStrategyMap.put(UploadFileTypeEnum.DOCX.getType(),factory.new ReadDOCXFileStrategy()); readFileHandleStrategyMap.put(UploadFileTypeEnum.ODF.getType(),factory.new ReadODFFileStrategy()); readFileHandleStrategyMap.put(UploadFileTypeEnum.WPS.getType(),factory.new ReadWPSFileStrategy()); readFileHandleStrategyMap.put(UploadFileTypeEnum.PDF.getType(),factory.new ReadPDFFileStrategy()); } public static IReadFileHandleStrategy getReadFileHandleStrategy(String filePath){ new ReadFileHandleStrategyFactory(); String fileType = filePath.substring(filePath.lastIndexOf(".")).toUpperCase(); if (StringUtils.isEmpty(fileType)) throw new ServiceException("文件路径错误,请重新提交!", 500); fileType = fileType.replace(".","").toUpperCase(); IReadFileHandleStrategy strategy = readFileHandleStrategyMap.get(fileType); if (strategy == null) throw new ServiceException("不支持的文件类型,请重新提交!", 500); return strategy; } }
  1. 策略接口 IReadFileHandleStrategy.java
import com.xxx.vo.ReadFileResultVO; /** * 文件读取接口 * @author wxz * @date 2023.4.12 * @version 1.0.0 */ public interface IReadFileHandleStrategy { ReadFileResultVO handleReadFile(String filePath); }
  1. 策略接口的实现 ReadFileFactoryImpl.java
import com.xxx.common.exception.ServiceException; import com.xxx.utils.ReadFileUtils; import com.xxx.utils.factory.api.IReadFileHandleStrategy; import com.xxx.vo.ReadFileResultVO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; /** * 根据绝对路径读取文件 * @author wxz * @version 1.0.0 * @date 2023.4.12 */ public class ReadFileFactoryImpl{ protected final Logger logger = LoggerFactory.getLogger(this.getClass()); ReadFileUtils utils = new ReadFileUtils(); /** * 根据绝对路径读取DOC文件 */ public class ReadDOCFileStrategy implements IReadFileHandleStrategy { @Override public ReadFileResultVO handleReadFile(String filePath) { try { return utils.readDOC(filePath); } catch (IOException e) { logger.error("文件读取失败,{}", e.getMessage()); throw new ServiceException("文件读取失败", 500); } } } /** * 读取DOCX文件 */ public class ReadDOCXFileStrategy implements IReadFileHandleStrategy { @Override public ReadFileResultVO handleReadFile(String filePath) { try { return utils.readDOCX(filePath); } catch (IOException e) { logger.error("文件读取失败,{}", e.getMessage()); throw new ServiceException("文件读取失败", 500); } } } /** * 读取ODF文件 */ public class ReadODFFileStrategy implements IReadFileHandleStrategy { @Override public ReadFileResultVO handleReadFile(String filePath) { return utils.readOFD(filePath); } } /** * 读取WPS文件 */ public class ReadWPSFileStrategy implements IReadFileHandleStrategy { @Override public ReadFileResultVO handleReadFile(String filePath) { return utils.readWPS(filePath); } } /** * 读取PDF文件 */ public class ReadPDFFileStrategy implements IReadFileHandleStrategy { @Override public ReadFileResultVO handleReadFile(String filePath) { try { return utils.readPdf(filePath); } catch (Exception e) { logger.error("文件读取失败,{}", e.getMessage()); throw new ServiceException("文件读取失败", 500); } } } }
  1. 执行流程大致如下所示

image.png

四、总结

经过上述重构,基本就能解决掉代码选择分支过多的问题。如果后续还需要读取更多的文件类型,则只需要:

  1. 实现 IReadFileHandleStrategy.java中的 handleReadFile()接口
  2. ReadFileHandleStrategyFactory 工厂中装配所扩展的方法即可( readFileHandleStrategyMap.put(文件类型枚举, factory.new 所调用的方法;)


评论区

登录后参与交流、获取后续更新提醒

目录
暂无数据