跳至主要內容

策略模式

Mr.Hope...大约 3 分钟

策略是一种行为设计模式, 它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换。

原始对象被称为上下文, 它包含指向策略对象的引用并将执行行为的任务分派给策略对象。 为了改变上下文完成其工作的方式, 其他对象可以使用另一个对象来替换当前链接的策略对象。

使用示例: 策略模式在 Java 代码中很常见。 它经常在各种框架中使用, 能在不扩展类的情况下向用户提供改变其行为的方式。

Java 8 开始支持 lambda 方法, 它可作为一种替代策略模式的简单方式。

这里有一些核心 Java 程序库中策略模式的示例:

识别方法: 策略模式可以通过允许嵌套对象完成实际工作的方法以及允许将该对象替换为不同对象的设置器来识别。

OSS存储内文件的内部数据提取方法

同一目录内存放的文件类型各种各样,可以采用不同的策略处理不同的文件类型。

依赖引入

<!--        Apache POI-->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>

strategies

strategies/FileHandler.java:通用的文件读取方法

/**
 * 处理文件接口(策略模式)
 */
public interface FileHandler {
    String handleFile(InputStream inputStream) throws IOException;
}

strategies/ExcelFileHandler.java:Excel 文件读取方法

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
public class ExcelFileHandler implements FileHandler {
    @Override
    public String handleFile(InputStream inputStream) throws IOException {
        StringBuilder sb = new StringBuilder();
        Workbook workbook = new XSSFWorkbook(inputStream);
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            Sheet sheet = workbook.getSheetAt(i);
            for (Row row : sheet) {
                for (Cell cell : row) {
                    switch (cell.getCellType()) {
                        case STRING:
                            sb.append(cell.getStringCellValue());
                            break;
                        case NUMERIC:
                            sb.append(cell.getNumericCellValue());
                            break;
                        case BOOLEAN:
                            sb.append(cell.getBooleanCellValue());
                            break;
                        case BLANK:
                            sb.append("[BLANK]");
                            break;
                        default:
                            sb.append("[UNKNOWN]");
                            break;
                    }
                    sb.append("\t");
                }
                sb.append("\n");
            }
        }
        workbook.close();
        return sb.toString();
    }
}

strategies/TextFileHandler.java:TXT 文件读取方法

public class TextFileHandler implements FileHandler {
    @Override
    public String handleFile(InputStream inputStream) throws IOException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        return outputStream.toString();
    }
}

strategies/WordFileHandler.java:word文件读取方法

import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.io.IOException;
import java.io.InputStream;
public class WordFileHandler implements FileHandler {
    @Override
    public String handleFile(InputStream inputStream) throws IOException {
        XWPFDocument doc = new XWPFDocument(inputStream);
        XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
        return extractor.getText();
    }
}

FileHandlerManager

class FileHandlerManager {
    private static final Map<String, FileHandler> fileHandlers;

    static {
        fileHandlers = new HashMap<>();
        initializeHandlers();
    }
    private static void initializeHandlers() {
        // 初始化不同类型文件处理器
        fileHandlers.put("txt", new TextFileHandler());
        fileHandlers.put("docx", new WordFileHandler());
        fileHandlers.put("doc", new WordFileHandler());
        fileHandlers.put("rtf", new WordFileHandler());
        fileHandlers.put("xlsx", new ExcelFileHandler());
    }

    public static FileHandler getFileHandler(String fileType) {
        // 根据文件类型获取对应的处理器
        return fileHandlers.get(fileType.toLowerCase());
    }
}

Demo

public class Main {
    public static void main(String[] args) {
        // 指定资源目录下的 doc 文件夹路径
        String folderPath = "src/main/resources/doc";

        // 获取目录下所有文件
        File folder = new File(folderPath);
        List<String> list = new ArrayList<>();
        if (folder.exists() && folder.isDirectory()) {
            File[] files = folder.listFiles(File::isFile);
            if (files != null) {
                // 遍历所有文件
                for (File file : files) {
                    String content = handleFile(file);
                    list.add(content);
                }
            } else {
                System.out.println("文件夹内无文件");
            }
        } else {
            System.out.println("文件夹不存在");
        }
        System.out.println(list);
    }

    @SneakyThrows
    private static String handleFile(File file) {
        // 获取文件的输入流
        InputStream inputStream = Files.newInputStream(file.toPath());

        // 获取文件后缀
        String fileName = file.getName();
        String[] fileNameParts = fileName.split("\\.");
        String fileExtension = fileNameParts[fileNameParts.length - 1];

        // 根据文件后缀选择不同的文件处理策略
        FileHandler fileHandler = FileHandlerManager.getFileHandler(fileExtension);
        if (fileHandler != null) {
            // 使用文件处理器处理文件
            return fileHandler.handleFile(inputStream);
        } else {
            inputStream.close();
            throw new RuntimeException("不支持的文件格式");
        }
    }
}