0
点赞
收藏
分享

微信扫一扫

Java 抽象类与接口在 Java17 及以上版本的现代应用实践

Java抽象类与接口的现代应用实践(Java 17+)

在Java 17及后续版本中,抽象类和接口的应用结合了记录类(Record)、密封类(Sealed Class)、模式匹配(Pattern Matching)等新特性,为代码设计带来了更多可能。下面通过实际案例展示这些技术的综合应用。

一、抽象类的现代应用:结合密封类与模式匹配

案例背景:设计一个图形处理系统,支持计算不同形状的面积和周长。

// 密封抽象类定义图形层次结构
public abstract sealed class Shape permits Circle, Rectangle, Triangle {
    // 抽象方法:计算面积
    public abstract double area();
    
    // 抽象方法:计算周长
    public abstract double perimeter();
    
    // 默认方法:显示图形信息
    public void displayInfo() {
        System.out.printf("%s - 面积: %.2f, 周长: %.2f%n", 
                          getClass().getSimpleName(), area(), perimeter());
    }
    
    // 静态工厂方法:使用模式匹配处理不同形状
    public static void processShape(Shape shape) {
        switch (shape) {
            case Circle c -> System.out.println("圆形: 半径=" + c.radius());
            case Rectangle r -> System.out.println("矩形: 长=" + r.length() + ", 宽=" + r.width());
            case Triangle t -> System.out.println("三角形: 边长=" + t.sideA() + ", " + t.sideB() + ", " + t.sideC());
        }
    }
}

// 使用记录类实现具体形状
public record Circle(double radius) implements Shape {
    @Override
    public double area() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double perimeter() {
        return 2 * Math.PI * radius;
    }
}

public record Rectangle(double length, double width) implements Shape {
    @Override
    public double area() {
        return length * width;
    }
    
    @Override
    public double perimeter() {
        return 2 * (length + width);
    }
}

public record Triangle(double sideA, double sideB, double sideC) implements Shape {
    @Override
    public double area() {
        double s = (sideA + sideB + sideC) / 2;
        return Math.sqrt(s * (s - sideA) * (s - sideB) * (s - sideC));
    }
    
    @Override
    public double perimeter() {
        return sideA + sideB + sideC;
    }
}

// 主程序演示
public class ShapeDemo {
    public static void main(String[] args) {
        Shape circle = new Circle(5.0);
        Shape rectangle = new Rectangle(4.0, 6.0);
        Shape triangle = new Triangle(3.0, 4.0, 5.0);
        
        circle.displayInfo();
        rectangle.displayInfo();
        triangle.displayInfo();
        
        Shape.processShape(circle);
    }
}

技术亮点

  1. 密封抽象类:使用sealed关键字限制子类范围,增强类型安全性
  2. 记录类实现:简化了数据类的定义,自动生成构造器、访问器和equals/hashCode
  3. 模式匹配:在switch语句中直接解构记录类的属性

二、接口的现代应用:函数式接口与默认方法组合

案例背景:实现一个简单的事件处理框架,支持事件发布和订阅。

import java.util.*;
import java.util.function.Consumer;

// 事件总线接口 - 使用函数式接口和默认方法
public interface EventBus {
    // 注册事件监听器
    void registerListener(String eventType, Consumer<Object> listener);
    
    // 发布事件
    void publishEvent(String eventType, Object data);
    
    // 默认方法:批量注册多个事件类型的监听器
    default void registerListeners(Map<String, Consumer<Object>> listeners) {
        listeners.forEach(this::registerListener);
    }
    
    // 静态工厂方法:创建基于内存的事件总线实现
    static EventBus inMemoryEventBus() {
        return new InMemoryEventBus();
    }
}

// 内存实现的事件总线
final class InMemoryEventBus implements EventBus {
    private final Map<String, List<Consumer<Object>>> listeners = new HashMap<>();
    
    @Override
    public void registerListener(String eventType, Consumer<Object> listener) {
        listeners.computeIfAbsent(eventType, k -> new ArrayList<>())
                 .add(listener);
    }
    
    @Override
    public void publishEvent(String eventType, Object data) {
        listeners.getOrDefault(eventType, Collections.emptyList())
                 .forEach(listener -> listener.accept(data));
    }
}

// 应用示例
public class EventBusDemo {
    public static void main(String[] args) {
        EventBus bus = EventBus.inMemoryEventBus();
        
        // 注册事件监听器
        bus.registerListener("user.login", data -> 
            System.out.printf("用户登录: %s%n", data));
        
        bus.registerListener("order.create", data -> 
            System.out.printf("订单创建: %s%n", data));
        
        // 发布事件
        bus.publishEvent("user.login", "testUser");
        bus.publishEvent("order.create", Map.of("id", "ORD123", "amount", 99.99));
    }
}

技术亮点

  1. 函数式接口:使用Consumer<T>作为事件监听器类型
  2. 默认方法扩展:提供registerListeners默认方法简化批量注册
  3. 静态工厂方法:通过inMemoryEventBus()创建实例,隐藏实现细节

三、混合使用抽象类与接口:实现复杂业务逻辑

案例背景:设计一个电商促销系统,支持不同类型的折扣策略。

import java.math.BigDecimal;
import java.util.*;

// 定义折扣策略接口
@FunctionalInterface
public interface DiscountStrategy {
    BigDecimal applyDiscount(BigDecimal originalPrice);
    
    // 默认方法:组合多个折扣策略
    default DiscountStrategy combine(DiscountStrategy next) {
        return price -> next.applyDiscount(this.applyDiscount(price));
    }
    
    // 静态方法:创建百分比折扣策略
    static DiscountStrategy percentage(double percent) {
        return price -> price.multiply(BigDecimal.valueOf(1 - percent / 100));
    }
    
    // 静态方法:创建固定金额折扣策略
    static DiscountStrategy fixedAmount(BigDecimal amount) {
        return price -> price.subtract(amount).max(BigDecimal.ZERO);
    }
}

// 抽象促销类
public abstract class Promotion {
    private final String name;
    private final DiscountStrategy strategy;
    
    protected Promotion(String name, DiscountStrategy strategy) {
        this.name = name;
        this.strategy = strategy;
    }
    
    public String getName() {
        return name;
    }
    
    public BigDecimal calculateDiscountedPrice(BigDecimal originalPrice) {
        return strategy.applyDiscount(originalPrice);
    }
    
    // 抽象方法:检查促销是否适用于给定商品
    public abstract boolean isApplicable(Product product);
}

// 具体促销实现
public class HolidayPromotion extends Promotion {
    private final Set<String> applicableCategories;
    
    public HolidayPromotion(String name, double discountPercent, String... categories) {
        super(name, DiscountStrategy.percentage(discountPercent));
        this.applicableCategories = Set.of(categories);
    }
    
    @Override
    public boolean isApplicable(Product product) {
        return applicableCategories.contains(product.getCategory());
    }
}

// 商品类
public record Product(String id, String name, String category, BigDecimal price) {}

// 购物车类
public class ShoppingCart {
    private final List<Product> items = new ArrayList<>();
    private final List<Promotion> promotions = new ArrayList<>();
    
    public void addItem(Product product) {
        items.add(product);
    }
    
    public void applyPromotion(Promotion promotion) {
        promotions.add(promotion);
    }
    
    public BigDecimal calculateTotal() {
        return items.stream()
            .map(product -> {
                // 查找适用的促销并应用最大折扣
                Optional<Promotion> bestPromotion = promotions.stream()
                    .filter(p -> p.isApplicable(product))
                    .max(Comparator.comparing(p -> 
                        product.price().subtract(p.calculateDiscountedPrice(product.price()))));
                
                return bestPromotion.map(p -> p.calculateDiscountedPrice(product.price()))
                                    .orElse(product.price());
            })
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

// 演示程序
public class EcommerceDemo {
    public static void main(String[] args) {
        Product laptop = new Product("P001", "笔记本电脑", "电子产品", new BigDecimal("5999"));
        Product headphones = new Product("P002", "耳机", "电子产品", new BigDecimal("899"));
        Product book = new Product("P003", "Java编程思想", "图书", new BigDecimal("129"));
        
        ShoppingCart cart = new ShoppingCart();
        cart.addItem(laptop);
        cart.addItem(headphones);
        cart.addItem(book);
        
        // 添加促销活动
        cart.applyPromotion(new HolidayPromotion("国庆促销", 15, "电子产品"));
        cart.applyPromotion(new HolidayPromotion("书香节", 20, "图书"));
        
        // 计算折扣后总价
        BigDecimal total = cart.calculateTotal();
        System.out.printf("原价: ¥%.2f%n", cart.calculateTotalWithoutDiscounts());
        System.out.printf("折扣后总价: ¥%.2f%n", total);
    }
}

技术亮点

  1. 函数式接口设计DiscountStrategy接口支持策略组合和静态工厂方法
  2. 抽象类封装公共行为Promotion类管理折扣策略并定义抽象适用性检查
  3. Java Stream API:在ShoppingCart中使用流式处理计算最优折扣

四、实战技巧总结

  1. 使用密封类增强类型安全:限制抽象类的子类范围,使代码更具可维护性
  2. 函数式接口简化回调:利用Java内置函数式接口减少样板代码
  3. 默认方法渐进式增强:在不破坏现有实现的前提下扩展接口功能
  4. 记录类替代数据类:对于简单数据载体,优先使用记录类而非普通类
  5. 模式匹配优化类型检查:简化条件分支中的类型判断和属性提取

通过结合这些现代Java特性,可以构建更加简洁、灵活且类型安全的抽象类和接口设计,充分发挥Java语言的优势。

Java 抽象类,Java 接口,Java17 新特性,抽象类应用,接口实现,现代 Java 开发,面向对象设计,默认方法,静态方法,抽象类接口区别,Java 编程实践,函数式接口,record 类,sealed 类,Java 开发最佳实践

代码获取方式 https://pan.quark.cn/s/14fcf913bae6

举报

相关推荐

0 条评论