【函数式接口使用✈️✈️】通过具体的例子实现函数结合策略模式的使用

目录

前言

一、核心函数式接口

[1. Consumer](#1. Consumer)

[2. Supplier](#2. Supplier)

[3. Function,>](#3. Function,>)

二、场景模拟

1.面向对象设计

[2. 策略接口实现(以 Function 接口作为策略)](#2. 策略接口实现(以 Function 接口作为策略))

三、对比


前言

在 Java 8 中引入了Stream API 新特性,这使得函数式编程风格进一步得到巩固,其中伴随着Lambda 表达式和 Stream API 的广泛使用,另一种函数式接口风格亦可以简化代码提升可读性和拓展性,具体如下

一、核心函数式接口

1.Consumer<T>

  • 定义了一个接受单一输入参数并且无返回值的操作。常用于数据处理流程中的消费型操作,如打印日志、更新数据库等。
java 复制代码
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
        names.forEach(e-> System.out.println("Welcome login : "+e));
        // 这里是使用的Consumer<String>,给一个参数执行相关操作

        // 或者定义一个自定义Consumer
        Consumer<String> logAction = name -> System.out.println("Logging action for: " + name);
        names.forEach(logAction);

2. Supplier<T>

  • 定义了一个不接受任何参数但是会产生一个结果的方法引用。常用于提供数据来源或计算某个值。
java 复制代码
        Supplier<Integer> randomIntSupplier = () -> ThreadLocalRandom.current().nextInt(1, 100);
        System.out.println(randomIntSupplier.get()); // 输出一个1到100之间的随机整数

3. Function<T, R>

  • 定义了一个接受一个输入参数并产生一个输出结果的方法引用。常用于数据转换、映射或计算。
java 复制代码
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        List<Double> doubles = numbers.stream().map((Function<Integer, Double>)                                 
        Integer::doubleValue).collect(Collectors.toList());
        doubles.forEach(System.out::println);

        // 或者自定义Function
        Function<String, String> upperCaseTransformer = String::toUpperCase;
        String transformed = upperCaseTransformer.apply("hello"); // 输出 "HELLO"
        System.out.println(transformed);

二、场景模拟

1.面向对象设计

比如常见的促销活动中,不同的促销策略计算出商品的最终价格是不一样的,采用传统的面向对象设计的话,需要为每一个促销活动创建独立的方法或者类了,并在购物车类中通过直接调用相应的方法计算,如下:

java 复制代码
public class ShoppingCart {
    //购物车中的商品列表
    private List<Product> products;

    //普通不打折,统计所有商品的价格即可
    public double calculateTotalPriceWithNormalPrice() {
        double totalPrice = products.stream()
                                    .map(Product::getPrice)
                                    .reduce(0.0, Double::sum);
        return totalPrice;
    }


    //促销打九折,统计商品价格的九折
    public double calculateTotalPriceWithTenPercentDiscount() {
        double totalPrice = products.stream()
                                    .map(product -> product.getPrice() * 0.9)
                                    .reduce(0.0, Double::sum);
        return totalPrice;
    }

    
    //促销直减50 ,小于0 的按照0元计算
    public double calculateTotalPriceWithFiftyDollarsOff() {
        double totalPrice = products.stream()
                                    .map(product -> Math.max(product.getPrice() - 50.0, 0.0))
                                    .reduce(0.0, Double::sum);
        return totalPrice;
    }

    // 调用示例
    public void processCheckout(CheckoutType type) {
        switch (type) {
            case NORMAL_PRICE:
                double normalPrice = calculateTotalPriceWithNormalPrice();
                // 处理正常价格结算逻辑
                break;
            case TEN_PERCENT_DISCOUNT:
                double tenPercentDiscount = calculateTotalPriceWithTenPercentDiscount();
                // 处理九折结算逻辑
                break;
            case FIFTY_DOLLARS_OFF:
                double fiftyDollarsOff = calculateTotalPriceWithFiftyDollarsOff();
                // 处理直减50美元结算逻辑
                break;
        }
    }

    // 其他方法...
}

enum CheckoutType {
    NORMAL_PRICE,
    TEN_PERCENT_DISCOUNT,
    FIFTY_DOLLARS_OFF
}

这种方式增加了代码的耦合度,并且如果需要新增或者修改促销策略,就需要修改ShoppingCart类

2. 策略接口实现(以 Function 接口作为策略)

java 复制代码
import java.util.function.Function;

public interface PromotionStrategy extends Function<Double, Double> {
    // 不需要额外的方法,因为Function本身就是一种策略(接受一个参数,返回一个结果),它接受原始价格并返回打折后的价格
}

创建几个具体的策略实现

java 复制代码
public class NormalPriceStrategy implements PromotionStrategy {
    @Override
    public Double apply(Double originalPrice) {
        return originalPrice; // 正常价格,不做打折处理
    }
}

public class TenPercentDiscountStrategy implements PromotionStrategy {
    @Override
    public Double apply(Double originalPrice) {
        return originalPrice * 0.9; // 打九折
    }
}

public class FiftyDollarsOffStrategy implements PromotionStrategy {
    @Override
    public Double apply(Double originalPrice) {
        return Math.max(originalPrice - 50.0, 0.0); // 直减50美元,价格不能低于0
    }
}

之后,在购物车计算逻辑中,可以根据用户选择的促销策略动态计算商品的价格:

java 复制代码
public class ShoppingCart {
    private List<Product> products;
    private PromotionStrategy promotionStrategy;

    public ShoppingCart(PromotionStrategy strategy) {
        this.promotionStrategy = strategy;
        // 初始化产品列表...
    }

    public double calculateTotalPrice() {
        double totalPrice = products.stream()
                                    .map(Product::getPrice)
                                    .map(promotionStrategy)
                                    .reduce(0.0, Double::sum);
        return totalPrice;
    }

    // 其他方法...
}

// 使用示例:
ShoppingCart cart = new ShoppingCart(new TenPercentDiscountStrategy());
// 添加商品到cart...
double finalPrice = cart.calculateTotalPrice(); // 根据策略计算总价

这个例子就是使用 PromotionStrategy 扮演了策略角色,不同的折扣策略通过实现 Function<Double,Double> 接口来决定如何计算折扣价,在使用时,可以根据需要选择并注入不同的策略实现。

三、对比

策略模式 面向对象设计
优点 * 开放封闭原则:策略模式鼓励对扩展开放,对修改封闭。当需要增加新的促销策略时,只需要增加一个新的策略类,不需要修改现有的购物车类或者其他已有代码。 * 代码复用 :每个策略类(如NormalPriceStrategyTenPercentDiscountStrategyFiftyDollarsOffStrategy)可以独立于购物车类使用,增强了代码的复用性。 * 低耦合:购物车类与具体的促销策略解耦,使得系统更灵活,更容易维护。 * 对于简单的场景,直接在购物车类中添加多个计算方法直观易懂,初学者更容易接受。
缺点 * 策略种类增多时,可能会导致策略接口的家族变得庞大,若策略逻辑差异不大,可能会造成代码冗余。 * 耦合度高:购物车类与具体的促销逻辑紧密耦合,当促销策略发生变化时,必须修改购物车类的代码。 * 扩展困难:若促销策略种类增加,会导致购物车类的代码臃肿,且不利于代码维护。 * 代码复用性差:对于每一种新的促销活动,都需要在购物车类中添加新的方法,无法直接复用现有逻辑。

其实不难看出,在面对频繁变化的业务逻辑(如促销策略)时,策略模式的优势明显,它有助于代码的可维护性、扩展性和复用性。而在简单、固定的场景下,直接在购物车类中硬编码计算逻辑可能显得更为直接简单。然而,考虑到长期的软件迭代和维护成本,推荐采用策略模式来优化代码结构。

文末

文章到这里就结束了~

相关推荐
waicsdn_haha4 小时前
Postman最新详细安装及使用教程【附安装包】
测试工具·api·压力测试·postman·策略模式·get·delete
越甲八千4 天前
简单工厂模式和策略模式的异同
简单工厂模式·策略模式
无奈何杨5 天前
LiteFlow决策系统的策略模式,顺序、最坏、投票、权重
策略模式·模型·规则引擎·决策
Adellle6 天前
判题机的开发(代码沙箱、三种模式、工厂模式、策略模式优化、代理模式)
java·后端·代理模式·策略模式
技术思考者7 天前
Java设计模式实战:策略模式、工厂模式、模板模式组合使用
java·设计模式·策略模式
Narutolxy8 天前
️ macOS 安装 Oracle Instant Client:详细教程与实践指南20241216
macos·oracle·策略模式
智慧城市20308 天前
78页PPT丨家居集团流程信息中心战略规划报告2020
阿里云·策略模式
xiaoduyyy9 天前
【Android】行为型设计模式—策略模式、模版方法模式、观察者模式
android·设计模式·策略模式
重生之Java开发工程师11 天前
⭐设计模式—策略模式
java·设计模式·面试·策略模式
庄小焱12 天前
设计模式——Singleton(单例)设计模式
设计模式·策略模式·系统设计