目录
前言
一、核心函数式接口
1. Consumer
2. Supplier
3. Function,>
二、场景模拟
1.面向对象设计
2. 策略接口实现(以 Function 接口作为策略)
三、对比
前言
在 Java 8 中引入了Stream API 新特性,这使得函数式编程风格进一步得到巩固,其中伴随着Lambda 表达式和 Stream API 的广泛使用,另一种函数式接口风格亦可以简化代码提升可读性和拓展性,具体如下
一、核心函数式接口
1. Consumer<T>
- 定义了一个接受单一输入参数并且无返回值的操作。常用于数据处理流程中的消费型操作,如打印日志、更新数据库等。
-
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>
- 定义了一个不接受任何参数但是会产生一个结果的方法引用。常用于提供数据来源或计算某个值。
-
Supplier<Integer> randomIntSupplier = () -> ThreadLocalRandom.current().nextInt(1, 100); System.out.println(randomIntSupplier.get()); // 输出一个1到100之间的随机整数
3. Function<T, R>
- 定义了一个接受一个输入参数并产生一个输出结果的方法引用。常用于数据转换、映射或计算。
-
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.面向对象设计
比如常见的促销活动中,不同的促销策略计算出商品的最终价格是不一样的,采用传统的面向对象设计的话,需要为每一个促销活动创建独立的方法或者类了,并在购物车类中通过直接调用相应的方法计算,如下:
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 接口作为策略)
import java.util.function.Function;
public interface PromotionStrategy extends Function<Double, Double> {
// 不需要额外的方法,因为Function本身就是一种策略(接受一个参数,返回一个结果),它接受原始价格并返回打折后的价格
}
创建几个具体的策略实现
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
}
}
之后,在购物车计算逻辑中,可以根据用户选择的促销策略动态计算商品的价格:
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> 接口来决定如何计算折扣价,在使用时,可以根据需要选择并注入不同的策略实现。
三、对比
策略模式 | 面向对象设计 | |
---|---|---|
优点 |
|
|
缺点 |
|
|
其实不难看出,在面对频繁变化的业务逻辑(如促销策略)时,策略模式的优势明显,它有助于代码的可维护性、扩展性和复用性。而在简单、固定的场景下,直接在购物车类中硬编码计算逻辑可能显得更为直接简单。然而,考虑到长期的软件迭代和维护成本,推荐采用策略模式来优化代码结构。
文末
文章到这里就结束了~