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语句块.

总体结构如下:
在这里插入图片描述

三、具体实现

  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. 执行流程大致如下所示

在这里插入图片描述

四、总结

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

  1. 实现 IReadFileHandleStrategy.java中的 handleReadFile()接口
  2. ReadFileHandleStrategyFactory 工厂中装配所扩展的方法即可( readFileHandleStrategyMap.put(文件类型枚举, factory.new 所调用的方法;)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值