• 【函数式接口使用✈️✈️】配合策略模式实现文件处理的案例


    目录

    🍸前言

    🍻一、功能描述

    🍺二、面向对象设计模式

    🍹三、策略模式

    🍦四、策略 VS 面向对象

    🍨章末


    🍸前言

            小伙伴们大家好,上周初步了解了下函数式接口,Consumer,Supplier,Function等接口的使用,以及结合而策略模式实现购物促销功能的案例实现,这里再配合实现文件处理的功能,案例比较简单,主要是看策略模式和普通面向对象模式的区别

    🍻一、功能描述

    假设我们需要实现一个文件处理器,能够读取文件内容,并根据不同的处理策略对文件内容进行处理,例如将文件内容转换为大写、小写或者进行加密。

    🍺二、面向对象设计模式

           (1) 这种方式逻辑比较清晰,就是创建一个文件处理器类,该类中有各种文件内容处理方法,比如内容转大写或者加密,文件处理器类如下:

    1. import java.io.BufferedReader;
    2. import java.io.FileReader;
    3. import java.io.IOException;
    4. public class FileProcessor {
    5. public void processFileToUpper(String filename) throws IOException {
    6. try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
    7. String line;
    8. while ((line = reader.readLine()) != null) {
    9. String processedLine = line.toUpperCase();
    10. System.out.println(processedLine); // 可替换为具体处理逻辑,比如写入到另一个文件
    11. }
    12. }
    13. }
    14. public void processFileToLower(String filename) throws IOException {
    15. try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
    16. String line;
    17. while ((line = reader.readLine()) != null) {
    18. String processedLine = line.toLowerCase();
    19. System.out.println(processedLine);
    20. }
    21. }
    22. }
    23. public void processFileEncrypt(String filename) throws IOException {
    24. try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
    25. String line;
    26. while ((line = reader.readLine()) != null) {
    27. // 这里只是演示,实际的加密算法应该更复杂
    28. String processedLine = line.replaceAll("[a-zA-Z]", "*");
    29. System.out.println(processedLine);
    30. }
    31. }
    32. }
    33. }

            (2)测试下,使用很简单,实例化一个文件处理器对象,通过对象调用其具体的处理方法即可

    1. import java.io.IOException;
    2. public class TestFile {
    3. public static void main(String[] args) {
    4. String filename = "C:\\Users\\ben.huang\\Desktop\\testFile.txt";
    5. FileProcessor fileProcessor = new FileProcessor();
    6. try {
    7. System.out.println("File content in uppercase:");
    8. fileProcessor.processFileToUpper(filename);
    9. System.out.println("\nFile content in lowercase:");
    10. fileProcessor.processFileToLower(filename);
    11. System.out.println("\nFile content encrypted:");
    12. fileProcessor.processFileEncrypt(filename);
    13. } catch (IOException e) {
    14. e.printStackTrace();
    15. }
    16. }
    17. }

    🍹三、策略模式

            (1)也是创建一个文件处理器类,不过该类中只有一个处理方法,具体地 实现功能要根据传入地函数名称去处理,文件处理器类如下:

    1. import java.io.BufferedReader;
    2. import java.io.FileNotFoundException;
    3. import java.io.FileReader;
    4. import java.io.IOException;
    5. import java.util.function.Consumer;
    6. import java.util.function.Function;
    7. import java.util.function.Supplier;
    8. /**
    9. * @author ben.huang
    10. */
    11. public class FileFunction {
    12. public void processFile (String fileName, Function processingStrategy) throws IOException {
    13. //supplier 相当于生产者,调用该函数会获取到文件地读取流
    14. Supplier fileReadSupplier = () ->{
    15. try {
    16. return new BufferedReader(new FileReader(fileName));
    17. } catch (FileNotFoundException e) {
    18. throw new RuntimeException("error opening file"+e);
    19. }
    20. };
    21. //相当于一个消费者,根据传入的函数去消费每一行读取到地数据
    22. Consumer fileProcessor = line ->{
    23. String apply = processingStrategy.apply(line);
    24. System.out.println(apply);
    25. };
    26. //获取输入流
    27. BufferedReader reader = fileReadSupplier.get();
    28. String line;
    29. //依次处理每行输入流
    30. while((line = reader.readLine()) != null){
    31. fileProcessor.accept(line);
    32. }
    33. }
    34. }

             (2)具体地文件处理函数可以单独写到一个类中,因为后期如果需要添加新的处理函数,直接在这里进行扩展即可,文件处理函数如下:

    1. import java.util.function.Function;
    2. /**
    3. * @author ben.huang
    4. */
    5. public class FileProcessingStrategies {
    6. //返回的是函数表达式
    7. public static Function toUpperCase(){
    8. return String::toUpperCase;
    9. }
    10. public static Function toLowerCase(){
    11. return String::toLowerCase;
    12. }
    13. public static Function encrypt(){
    14. return str -> str.replaceAll("[a-zA-Z]","*");
    15. }
    16. }

            (3)测试下

    1. import java.io.IOException;
    2. /**
    3. * @author ben.huang
    4. */
    5. public class TestFileFunction {
    6. public static void main(String[] args) {
    7. String fileName = "C:\\Users\\ben.huang\\Desktop\\testFile.txt";
    8. FileFunction fileFunction = new FileFunction();
    9. try {
    10. //方法调用的时候,传入需要的处理函数即可
    11. System.out.println("File content in uppercase:");
    12. fileFunction.processFile(fileName,FileProcessingStrategies.toUpperCase());
    13. System.out.println("\nFile content in lowercase:");
    14. fileFunction.processFile(fileName,FileProcessingStrategies.toLowerCase());
    15. System.out.println("\nFile content in encrypted:");
    16. fileFunction.processFile(fileName,FileProcessingStrategies.encrypt());
    17. } catch (IOException e) {
    18. throw new RuntimeException(e);
    19. }
    20. }
    21. }

    🍦四、策略 VS 面向对象

             首先来看面向对象设计模式,这种方式是我在初学地时候最喜欢的编码方式,这种逻辑方便观看,易读性强,调用方便,代码方便别人阅读,修改方便,直接CV修改修改就行,整个功能在一个类中全部实现,省了来回跳看的眼花,还有....(等等,串台了(bushi))

            那我们为社么还要用策略模式呢?

    不知大家可曾听闻开闭原则,依鄙人来看就是说不要去修改原有的类,而是去扩展。比如说,现在又加了几个文件处理器功能,策略模式只需要在策略函数类中新增几个函数,如果使用面向对象的话,需要新增几个方法,并且这些方法中有很多代码重复,冗余度很高

            总的来说,策略模式更加直接,通过定义不同的策略类来实现不同的功能,并且可以在运行时动态切换策略。而面向对象设计模式则更加灵活,可以根据具体的需求选择不同的设计模式来实现文件处理功能

    🍬后续补充

            用的比较少的话还是生疏,再给大家举几案例吧

    🍧案例一、比如根据不同的商品进行不同的税费计算

            分析:按照不同商品进行计算处理,简单的方法就是使用 if else 判断属于哪种商品,然后进行对应的计算操作。使用策略模式是这样,每个商品都要计算,那么可以把计算操作当作一个接口,不同的计算逻辑可以实现该接口,然后创建一个处理类,包含具体的计算实现类,以及调用实现类方法,代码如下:
            (1)计算方法接口定义

    1. interface TaxStrategy {
    2. double calculateTax(double amount);
    3. }

            (2)计算方法具体实现类

    1. class BasicTaxStrategy implements TaxStrategy {
    2. @Override
    3. public double calculateTax(double amount) {
    4. return amount * 0.1; // 基本税率为10%
    5. }
    6. }
    7. class LuxuryTaxStrategy implements TaxStrategy {
    8. @Override
    9. public double calculateTax(double amount) {
    10. return amount * 0.2; // 奢侈品税率为20%
    11. }
    12. }
    13. class FoodTaxStrategy implements TaxStrategy {
    14. @Override
    15. public double calculateTax(double amount) {
    16. return amount * 0.05; // 食品税率为5%
    17. }
    18. }

             (3)计算处理类,使用 Function 函数式接口代表具体的计算策略,构造方法接收一个函数参数,处理方法中的  apply 方法会接受一个参数,处理后返回一个参数

    1. class TaxCalculator {
    2. private Function taxStrategy;
    3. public TaxCalculator(Function taxStrategy) {
    4. this.taxStrategy = taxStrategy;
    5. }
    6. public double calculateTax(double amount) {
    7. return taxStrategy.apply(amount);
    8. }
    9. }
    10. //使用的时候像这样,传入一个实现类,则调用的就是这个实现类的计算方法
    11. //TaxCalculator taxCalculator = new TaxCalculator(new BasicTaxStrategy()::calculateTax);
    12. //double calculate = taxCalculator.calculate(100);

    🍨章末

            文章到这里就结束了~

  • 相关阅读:
    HTML5七夕情人节表白网页制作【新年倒计时白色雪花飘落】HTML+CSS+JavaScript CSS特效
    【云原生之Docker实战】使用Docker部署Prometheus 服务监控系统
    L48.linux命令每日一练 -- 第七章 Linux用户管理及用户信息查询命令 -- last、lastb和lastlog
    MyBatis
    服务器和客户端信息的获取
    【算法思想】贪心
    基于springboot接口的编写
    Spring面试题16:Spring框架中的单例bean是线程安全的吗?Spring框架中bean的生命周期?哪些是重要的bean生命周期方法?
    thinkphp:数据库查询操作六:查询的数据是否为空,如果为空就设置为0,并且保留数据小数点,查询的数据是时间戳转换为时间
    本地开发环境和服务器传输数据的几种方法
  • 原文地址:https://blog.csdn.net/TM007_/article/details/138073726