下载工作台
Java 编程实战

接口、抽象类、enum 与 record

试读上半部分 · 解锁后可读全文

第 6 章 · 接口、抽象类、enum 与 record

本章目标:理解接口抽象类的差异与选用;掌握 implements、默认方法与静态接口方法;熟练使用 enum 表达有限状态;了解 record(Java 16+)简化数据载体;扩展 toolkit-demo 的可定价订单状态模型;对照 python-devabc 与枚举。

学时建议:4 小时(含 1.5 小时跟练)

前置:完成 java-dev ch05;建议了解 python-dev 中 Enum 与抽象基类概念。


6.1 场景说明:定价策略与订单状态

toolkit-demo 需要:

  1. 多种定价策略(标准价、会员价、批发价)——用接口统一 priceFor
  2. 订单状态有限集合 —— 用 enum 替代字符串常量。
  3. 订单摘要只读数据 —— 用 record 承载。
learn-java/toolkit-demo/src/main/java/demo/contract/
  ├── Pricable.java
  ├── PricingStrategy.java + 实现类
  ├── OrderStatus.java
  ├── OrderSummary.java (record)
  └── PricingDemo.java

6.2 接口与抽象类

接口定义契约,支持 implements 多实现;Java 8+ 可有 default/static 方法。抽象类可有字段与构造器,适合模板方法。

抽象类接口
单继承、可有实现多实现、契约为主
共享状态与代码能力标记、策略

选用:共享代码用抽象类;多种可替换策略用接口(见 6.3 完整实现)。


6.3 定价策略完整实现

Pricable.java

package demo.contract;

public interface Pricable {
    String getSku();
    double getBasePrice();
}

PricingStrategy.java

package demo.contract;

public interface PricingStrategy {

    double priceFor(Pricable item, int quantity);

    default double lineTotal(Pricable item, int quantity) {
        if (quantity <= 0) {
            return 0.0;
        }
        return priceFor(item, quantity) * quantity;
    }
}

StandardPricing.java

package demo.contract;

public class StandardPricing implements PricingStrategy {
    @Override
    public double priceFor(Pricable item, int quantity) {
        return item.getBasePrice();
    }
}

MemberPricing.java

package demo.contract;

public class MemberPricing implements PricingStrategy {
    private final double rate;

    public MemberPricing(double rate) {
        this.rate = rate;
    }

    @Override
    public double priceFor(Pricable item, int quantity) {
        return item.getBasePrice() * rate;
    }
}

AbstractBulkPricing.java(模板方法基类)

package demo.contract;

/**
 * 批量定价抽象基类 — 模板方法模式:
 * priceFor 固定「取基价 → 按数量计价」流程,
 * 具体计价规则交由子类 applyRate 实现。
 */
public abstract class AbstractBulkPricing implements PricingStrategy {

    private final int threshold;
    private final double rate;

    protected AbstractBulkPricing(int threshold, double rate) {
        if (threshold <= 0) {
            throw new IllegalArgumentException("阈值须为正数:" + threshold);
        }
        if (rate <= 0 || rate > 1) {
            throw new IllegalArgumentException("费率须在 (0,1]:" + rate);
        }
        this.threshold = threshold;
        this.rate = rate;
    }

    protected int getThreshold() {
        return threshold;
    }

    protected double getRate() {
        return rate;
    }

    /** 模板方法:声明为 final,防止子类破坏固定流程 */
    @Override
    public final double priceFor(Pricable item, int quantity) {
        double base = item.getBasePrice();
        return applyRate(base, quantity);
    }

    /** 子类实现:根据数量决定是否应用费率 */
    protected abstract double applyRate(double base, int quantity);
}

BulkPricing.java

package demo.contract;

public class BulkPricing extends AbstractBulkPricing {
    public BulkPricing(int threshold, double rate) {
        super(threshold, rate);
    }
    @Override
    protected double applyRate(double base, int quantity) {
        return quantity >= getThreshold() ? base * getRate() : base;
    }
}

AbstractBulkPricingpriceFor模板方法(final,固定流程),applyRate钩子方法(abstract,子类填规则)——这是抽象类区别于接口的典型用法:接口定契约,抽象类定流程。

SimpleItem.java(Pricable 实现)

package demo.contract;

public class SimpleItem implements Pricable {
    private final String sku;
    private final String name;
    private final double basePrice;

    public SimpleItem(String sku, String name, double basePrice) {
        this.sku = sku;
        this.name = name;
        this.basePrice = basePrice;
    }

    @Override
    public String getSku() {
        return sku;
    }

    @Override
    public double getBasePrice() {
        return basePrice;
    }

    public String getName() {
        return name;
    }
}

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。